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") }