Skip to content

Commit d0e6392

Browse files
committed
fix roblox oauth
1 parent b931652 commit d0e6392

File tree

5 files changed

+92
-11
lines changed

5 files changed

+92
-11
lines changed

server/constants/auth_methods.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ const (
2727
AuthRecipeMethodMicrosoft = "microsoft"
2828
// AuthRecipeMethodTwitch is the twitch auth method
2929
AuthRecipeMethodTwitch = "twitch"
30+
// AuthRecipeMethodRoblox is the roblox auth method
31+
AuthRecipeMethodRoblox = "roblox"
3032
)

server/constants/oauth_info_urls.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ const (
1717

1818
TwitterUserInfoURL = "https://api.twitter.com/2/users/me?user.fields=id,name,profile_image_url,username"
1919

20+
// RobloxUserInfoURL is the URL to get user info from Roblox
21+
RobloxUserInfoURL = "https://apis.roblox.com/oauth/v1/userinfo"
22+
2023
DiscordUserInfoURL = "https://discord.com/api/oauth2/@me"
2124
// Get microsoft user info.
2225
// Ref: https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo

server/handlers/oauth_callback.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ func OAuthCallbackHandler() gin.HandlerFunc {
8989
user, err = processMicrosoftUserInfo(ctx, oauthCode)
9090
case constants.AuthRecipeMethodTwitch:
9191
user, err = processTwitchUserInfo(ctx, oauthCode)
92+
case constants.AuthRecipeMethodRoblox:
93+
user, err = processRobloxUserInfo(ctx, oauthCode, sessionState)
9294
default:
9395
log.Info("Invalid oauth provider")
9496
err = fmt.Errorf(`invalid oauth provider`)
@@ -818,3 +820,68 @@ func processTwitchUserInfo(ctx context.Context, code string) (*models.User, erro
818820

819821
return user, nil
820822
}
823+
824+
// process roblox user information
825+
func processRobloxUserInfo(ctx context.Context, code, verifier string) (*models.User, error) {
826+
oauth2Token, err := oauth.OAuthProviders.RobloxConfig.Exchange(ctx, code, oauth2.SetAuthURLParam("code_verifier", verifier))
827+
if err != nil {
828+
log.Debug("Failed to exchange code for token: ", err)
829+
return nil, fmt.Errorf("invalid roblox exchange code: %s", err.Error())
830+
}
831+
832+
client := http.Client{}
833+
req, err := http.NewRequest("GET", constants.RobloxUserInfoURL, nil)
834+
if err != nil {
835+
log.Debug("Failed to create roblox user info request: ", err)
836+
return nil, fmt.Errorf("error creating roblox user info request: %s", err.Error())
837+
}
838+
req.Header = http.Header{
839+
"Authorization": []string{fmt.Sprintf("Bearer %s", oauth2Token.AccessToken)},
840+
}
841+
842+
response, err := client.Do(req)
843+
if err != nil {
844+
log.Debug("Failed to request roblox user info: ", err)
845+
return nil, err
846+
}
847+
848+
defer response.Body.Close()
849+
body, err := io.ReadAll(response.Body)
850+
if err != nil {
851+
log.Debug("Failed to read roblox user info response body: ", err)
852+
return nil, fmt.Errorf("failed to read roblox response body: %s", err.Error())
853+
}
854+
855+
if response.StatusCode >= 400 {
856+
log.Debug("Failed to request roblox user info: ", string(body))
857+
return nil, fmt.Errorf("failed to request roblox user info: %s", string(body))
858+
}
859+
860+
userRawData := make(map[string]interface{})
861+
json.Unmarshal(body, &userRawData)
862+
863+
// log.Info(userRawData)
864+
nameArr := strings.SplitAfterN(userRawData["name"].(string), " ", 2)
865+
firstName := nameArr[0]
866+
lastName := ""
867+
if len(nameArr) == 2 {
868+
lastName = nameArr[1]
869+
}
870+
nickname := userRawData["nickname"].(string)
871+
profilePicture := userRawData["picture"].(string)
872+
email := ""
873+
if val, ok := userRawData["email"]; ok {
874+
email = val.(string)
875+
} else {
876+
email = userRawData["preferred_username"].(string)
877+
}
878+
user := &models.User{
879+
GivenName: &firstName,
880+
FamilyName: &lastName,
881+
Picture: &profilePicture,
882+
Nickname: &nickname,
883+
Email: &email,
884+
}
885+
886+
return user, nil
887+
}

server/handlers/oauth_login.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,24 @@ func OAuthLoginHandler() gin.HandlerFunc {
265265
oauth.OAuthProviders.TwitchConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodTwitch
266266
url := oauth.OAuthProviders.TwitchConfig.AuthCodeURL(oauthStateString)
267267
c.Redirect(http.StatusTemporaryRedirect, url)
268+
case constants.AuthRecipeMethodRoblox:
269+
if oauth.OAuthProviders.RobloxConfig == nil {
270+
log.Debug("RobloxConfig OAuth provider is not configured")
271+
isProviderConfigured = false
272+
break
273+
}
274+
err := memorystore.Provider.SetState(oauthStateString, constants.AuthRecipeMethodRoblox)
275+
if err != nil {
276+
log.Debug("Error setting state: ", err)
277+
c.JSON(500, gin.H{
278+
"error": "internal server error",
279+
})
280+
return
281+
}
282+
// during the init of OAuthProvider authorizer url might be empty
283+
oauth.OAuthProviders.RobloxConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodRoblox
284+
url := oauth.OAuthProviders.RobloxConfig.AuthCodeURL(oauthStateString)
285+
c.Redirect(http.StatusTemporaryRedirect, url)
268286
default:
269287
log.Debug("Invalid oauth provider: ", provider)
270288
c.JSON(422, gin.H{

server/oauth/oauth.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ type OIDCProvider struct {
4242
GoogleOIDC *oidc.Provider
4343
MicrosoftOIDC *oidc.Provider
4444
TwitchOIDC *oidc.Provider
45-
RobloxOIDC *oidc.Provider
4645
}
4746

4847
var (
@@ -261,22 +260,14 @@ func InitOAuth() error {
261260
if err != nil {
262261
robloxClientSecret = ""
263262
}
264-
265263
if robloxClientID != "" && robloxClientSecret != "" {
266-
p, err := oidc.NewProvider(ctx, "https://apis.roblox.com/oauth")
267-
if err != nil {
268-
log.Debugf(ctx, "Error while creating OIDC provider for roblox: %v", err)
269-
return err
270-
}
271-
272-
OIDCProviders.RobloxOIDC = p
273264
OAuthProviders.RobloxConfig = &oauth2.Config{
274265
ClientID: robloxClientID,
275266
ClientSecret: robloxClientSecret,
276267
RedirectURL: "/oauth_callback/roblox",
277268
Endpoint: oauth2.Endpoint{
278-
AuthURL: "https://apis.roblox.com/oauth/authorize",
279-
TokenURL: "https://apis.roblox.com/oauth/token",
269+
AuthURL: "https://apis.roblox.com/oauth/v1/authorize",
270+
TokenURL: "https://apis.roblox.com/oauth/v1/token",
280271
},
281272
Scopes: []string{oidc.ScopeOpenID, "profile"},
282273
}

0 commit comments

Comments
 (0)