fix roblox oauth
This commit is contained in:
parent
b931652769
commit
d0e6392f1a
|
@ -27,4 +27,6 @@ const (
|
||||||
AuthRecipeMethodMicrosoft = "microsoft"
|
AuthRecipeMethodMicrosoft = "microsoft"
|
||||||
// AuthRecipeMethodTwitch is the twitch auth method
|
// AuthRecipeMethodTwitch is the twitch auth method
|
||||||
AuthRecipeMethodTwitch = "twitch"
|
AuthRecipeMethodTwitch = "twitch"
|
||||||
|
// AuthRecipeMethodRoblox is the roblox auth method
|
||||||
|
AuthRecipeMethodRoblox = "roblox"
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,6 +17,9 @@ const (
|
||||||
|
|
||||||
TwitterUserInfoURL = "https://api.twitter.com/2/users/me?user.fields=id,name,profile_image_url,username"
|
TwitterUserInfoURL = "https://api.twitter.com/2/users/me?user.fields=id,name,profile_image_url,username"
|
||||||
|
|
||||||
|
// RobloxUserInfoURL is the URL to get user info from Roblox
|
||||||
|
RobloxUserInfoURL = "https://apis.roblox.com/oauth/v1/userinfo"
|
||||||
|
|
||||||
DiscordUserInfoURL = "https://discord.com/api/oauth2/@me"
|
DiscordUserInfoURL = "https://discord.com/api/oauth2/@me"
|
||||||
// Get microsoft user info.
|
// Get microsoft user info.
|
||||||
// Ref: https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo
|
// Ref: https://learn.microsoft.com/en-us/azure/active-directory/develop/userinfo
|
||||||
|
|
|
@ -89,6 +89,8 @@ func OAuthCallbackHandler() gin.HandlerFunc {
|
||||||
user, err = processMicrosoftUserInfo(ctx, oauthCode)
|
user, err = processMicrosoftUserInfo(ctx, oauthCode)
|
||||||
case constants.AuthRecipeMethodTwitch:
|
case constants.AuthRecipeMethodTwitch:
|
||||||
user, err = processTwitchUserInfo(ctx, oauthCode)
|
user, err = processTwitchUserInfo(ctx, oauthCode)
|
||||||
|
case constants.AuthRecipeMethodRoblox:
|
||||||
|
user, err = processRobloxUserInfo(ctx, oauthCode, sessionState)
|
||||||
default:
|
default:
|
||||||
log.Info("Invalid oauth provider")
|
log.Info("Invalid oauth provider")
|
||||||
err = fmt.Errorf(`invalid oauth provider`)
|
err = fmt.Errorf(`invalid oauth provider`)
|
||||||
|
@ -818,3 +820,68 @@ func processTwitchUserInfo(ctx context.Context, code string) (*models.User, erro
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process roblox user information
|
||||||
|
func processRobloxUserInfo(ctx context.Context, code, verifier string) (*models.User, error) {
|
||||||
|
oauth2Token, err := oauth.OAuthProviders.RobloxConfig.Exchange(ctx, code, oauth2.SetAuthURLParam("code_verifier", verifier))
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to exchange code for token: ", err)
|
||||||
|
return nil, fmt.Errorf("invalid roblox exchange code: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
client := http.Client{}
|
||||||
|
req, err := http.NewRequest("GET", constants.RobloxUserInfoURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to create roblox user info request: ", err)
|
||||||
|
return nil, fmt.Errorf("error creating roblox user info request: %s", err.Error())
|
||||||
|
}
|
||||||
|
req.Header = http.Header{
|
||||||
|
"Authorization": []string{fmt.Sprintf("Bearer %s", oauth2Token.AccessToken)},
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to request roblox user info: ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer response.Body.Close()
|
||||||
|
body, err := io.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Failed to read roblox user info response body: ", err)
|
||||||
|
return nil, fmt.Errorf("failed to read roblox response body: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode >= 400 {
|
||||||
|
log.Debug("Failed to request roblox user info: ", string(body))
|
||||||
|
return nil, fmt.Errorf("failed to request roblox user info: %s", string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
userRawData := make(map[string]interface{})
|
||||||
|
json.Unmarshal(body, &userRawData)
|
||||||
|
|
||||||
|
// log.Info(userRawData)
|
||||||
|
nameArr := strings.SplitAfterN(userRawData["name"].(string), " ", 2)
|
||||||
|
firstName := nameArr[0]
|
||||||
|
lastName := ""
|
||||||
|
if len(nameArr) == 2 {
|
||||||
|
lastName = nameArr[1]
|
||||||
|
}
|
||||||
|
nickname := userRawData["nickname"].(string)
|
||||||
|
profilePicture := userRawData["picture"].(string)
|
||||||
|
email := ""
|
||||||
|
if val, ok := userRawData["email"]; ok {
|
||||||
|
email = val.(string)
|
||||||
|
} else {
|
||||||
|
email = userRawData["preferred_username"].(string)
|
||||||
|
}
|
||||||
|
user := &models.User{
|
||||||
|
GivenName: &firstName,
|
||||||
|
FamilyName: &lastName,
|
||||||
|
Picture: &profilePicture,
|
||||||
|
Nickname: &nickname,
|
||||||
|
Email: &email,
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
|
@ -265,6 +265,24 @@ func OAuthLoginHandler() gin.HandlerFunc {
|
||||||
oauth.OAuthProviders.TwitchConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodTwitch
|
oauth.OAuthProviders.TwitchConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodTwitch
|
||||||
url := oauth.OAuthProviders.TwitchConfig.AuthCodeURL(oauthStateString)
|
url := oauth.OAuthProviders.TwitchConfig.AuthCodeURL(oauthStateString)
|
||||||
c.Redirect(http.StatusTemporaryRedirect, url)
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
|
case constants.AuthRecipeMethodRoblox:
|
||||||
|
if oauth.OAuthProviders.RobloxConfig == nil {
|
||||||
|
log.Debug("RobloxConfig OAuth provider is not configured")
|
||||||
|
isProviderConfigured = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
err := memorystore.Provider.SetState(oauthStateString, constants.AuthRecipeMethodRoblox)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("Error setting state: ", err)
|
||||||
|
c.JSON(500, gin.H{
|
||||||
|
"error": "internal server error",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// during the init of OAuthProvider authorizer url might be empty
|
||||||
|
oauth.OAuthProviders.RobloxConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodRoblox
|
||||||
|
url := oauth.OAuthProviders.RobloxConfig.AuthCodeURL(oauthStateString)
|
||||||
|
c.Redirect(http.StatusTemporaryRedirect, url)
|
||||||
default:
|
default:
|
||||||
log.Debug("Invalid oauth provider: ", provider)
|
log.Debug("Invalid oauth provider: ", provider)
|
||||||
c.JSON(422, gin.H{
|
c.JSON(422, gin.H{
|
||||||
|
|
|
@ -42,7 +42,6 @@ type OIDCProvider struct {
|
||||||
GoogleOIDC *oidc.Provider
|
GoogleOIDC *oidc.Provider
|
||||||
MicrosoftOIDC *oidc.Provider
|
MicrosoftOIDC *oidc.Provider
|
||||||
TwitchOIDC *oidc.Provider
|
TwitchOIDC *oidc.Provider
|
||||||
RobloxOIDC *oidc.Provider
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -261,22 +260,14 @@ func InitOAuth() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
robloxClientSecret = ""
|
robloxClientSecret = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if robloxClientID != "" && robloxClientSecret != "" {
|
if robloxClientID != "" && robloxClientSecret != "" {
|
||||||
p, err := oidc.NewProvider(ctx, "https://apis.roblox.com/oauth")
|
|
||||||
if err != nil {
|
|
||||||
log.Debugf(ctx, "Error while creating OIDC provider for roblox: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
OIDCProviders.RobloxOIDC = p
|
|
||||||
OAuthProviders.RobloxConfig = &oauth2.Config{
|
OAuthProviders.RobloxConfig = &oauth2.Config{
|
||||||
ClientID: robloxClientID,
|
ClientID: robloxClientID,
|
||||||
ClientSecret: robloxClientSecret,
|
ClientSecret: robloxClientSecret,
|
||||||
RedirectURL: "/oauth_callback/roblox",
|
RedirectURL: "/oauth_callback/roblox",
|
||||||
Endpoint: oauth2.Endpoint{
|
Endpoint: oauth2.Endpoint{
|
||||||
AuthURL: "https://apis.roblox.com/oauth/authorize",
|
AuthURL: "https://apis.roblox.com/oauth/v1/authorize",
|
||||||
TokenURL: "https://apis.roblox.com/oauth/token",
|
TokenURL: "https://apis.roblox.com/oauth/v1/token",
|
||||||
},
|
},
|
||||||
Scopes: []string{oidc.ScopeOpenID, "profile"},
|
Scopes: []string{oidc.ScopeOpenID, "profile"},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user