tripwire/auth.go

196 lines
4.4 KiB
Go

package main
import (
"crypto/x509"
"net/http"
"github.com/gorilla/mux"
)
func rootEndpoint(w http.ResponseWriter, r *http.Request) {
skinDomains := []string{
config.BaseUrl,
}
response := YggdrasilInfo{
Status: "OK",
RuntimeMode: "productionMode",
AppAuthor: "Tripwire Team",
AppDescription: "Custom Yggdrasil authentication server",
SpecVersion: "5.2.0",
AppName: "tripwire.yggdrasil",
ImplVersion: "5.2.0",
AppOwner: "Who knows?",
//Used by authlib-injector
SkinDomains: skinDomains,
}
if publicKey != nil {
pubkey, err := x509.MarshalPKIXPublicKey(publicKey)
if err == nil {
pubKeyString := string(encodePem(pubkey, "PUBLIC KEY"))
response.PublicKey = &pubKeyString
}
}
sendJSON(w, response)
}
func authenticateEndpoint(w http.ResponseWriter, r *http.Request) {
var authPayload AuthPayload
err := unmarshalTo(r, &authPayload)
if err != nil {
handleError(w, err)
return
}
// checks username and password
authToken, err := getAuthToken(authPayload.Username, authPayload.Password)
if err != nil {
err := YggError{
Code: 403,
Error: "ForbiddenOperationException",
ErrorMessage: "Invalid credentials.",
}
sendError(w, err)
return
}
// authenticated at this point
clientToken, err := checkClientToken(authPayload.ClientToken, authPayload.Username)
if err != nil {
handleError(w, err)
return
}
player, err := getPlayerByUsername(authPayload.Username)
if err != nil {
handleError(w, err)
return
}
profile := MCProfile{authPayload.Username, player.UUID}
authResponse := AuthResponse{
ClientToken: clientToken,
AccessToken: authToken,
AvailableProfiles: []MCProfile{
profile,
},
SelectedProfile: profile,
}
sendJSON(w, authResponse)
}
func addUserEndpoint(w http.ResponseWriter, r *http.Request) {
var user UserCredentials
err := unmarshalTo(r, &user)
if err != nil {
handleError(w, err)
return
}
// add user to db
newPassword, err := createUser(user.Username, user.Password)
if err != nil {
handleError(w, err)
return
}
// in this case, password is the admin token, not the password to assign
// send response
respAccount := UserCredentials{
Username: user.Username,
Password: newPassword,
}
sendJSON(w, respAccount)
}
func refreshTokenEndpoint(w http.ResponseWriter, r *http.Request) {
var refreshPayload RefreshPayload
err := unmarshalTo(r, &refreshPayload)
if err != nil {
handleError(w, err)
return
}
responsePayload, err := refreshTokens(refreshPayload)
if err != nil {
handleError(w, err)
return
}
if refreshPayload == responsePayload {
err := YggError{
Code: 403,
Error: "ForbiddenOperationException",
ErrorMessage: "Invalid token.",
}
sendError(w, err)
return
}
sendJSON(w, responsePayload)
}
func validateEndpoint(w http.ResponseWriter, r *http.Request) {
var refreshPayload RefreshPayload
err := unmarshalTo(r, &refreshPayload)
if err != nil {
handleError(w, err)
return
}
isValid, err := validateTokens(refreshPayload.AccessToken, refreshPayload.ClientToken)
if err != nil {
handleError(w, err)
return
}
if !isValid {
err := YggError{
Code: 403,
Error: "ForbiddenOperationException",
ErrorMessage: "Invalid token.",
}
sendError(w, err)
return
}
sendEmpty(w)
}
func signoutEndpoint(w http.ResponseWriter, r *http.Request) {
var creds UserCredentials
err := unmarshalTo(r, &creds)
if err != nil {
handleError(w, err)
return
}
err = invalidateTokensWithLogin(creds.Username, creds.Password)
if err != nil {
handleError(w, err)
return
}
sendEmpty(w)
}
func invalidateEndpoint(w http.ResponseWriter, r *http.Request) {
var refreshPayload RefreshPayload
err := unmarshalTo(r, &refreshPayload)
if err != nil {
handleError(w, err)
return
}
err = invalidateTokens(refreshPayload.AccessToken, refreshPayload.ClientToken)
if err != nil {
handleError(w, err)
return
}
sendEmpty(w)
}
func registerAuthEndpoints(r *mux.Router) {
prefix := "/authserver"
r.HandleFunc(prefix+"/", rootEndpoint)
r.HandleFunc(prefix+"/authenticate", authenticateEndpoint).Methods("POST")
r.HandleFunc(prefix+"/refresh", refreshTokenEndpoint).Methods("POST")
r.HandleFunc(prefix+"/signout", signoutEndpoint).Methods("POST")
r.HandleFunc(prefix+"/invalidate", invalidateEndpoint).Methods("POST")
r.HandleFunc(prefix+"/validate", validateEndpoint).Methods("POST")
r.HandleFunc(prefix+"/admin/addUser", addUserEndpoint).Methods("POST")
}