Compare commits

...

11 Commits

Author SHA1 Message Date
Lakhan Samani
88f9a10f21 Merge pull request #192 from authorizerdev/feat/apple-login
feat: add apple login
2022-06-16 09:48:02 +05:30
Lakhan Samani
4e08d4f8fd fix: update app 2022-06-16 09:47:16 +05:30
Lakhan Samani
1c4dda9299 fix: remove debug logs 2022-06-16 07:34:10 +05:30
Lakhan Samani
ab18fa5832 fix: use raw base64 url decoding 2022-06-15 21:55:41 +05:30
Lakhan Samani
484d0c0882 chore: update app 2022-06-14 16:39:06 +05:30
Lakhan Samani
be59c3615f fix: add comment for scope 2022-06-14 15:47:08 +05:30
Lakhan Samani
db351f7771 fix: remove debug logs 2022-06-14 15:45:06 +05:30
Lakhan Samani
91c29c4092 fix: redirect 2022-06-14 15:43:23 +05:30
Lakhan Samani
415b97535e fix: update scope param 2022-06-14 15:05:56 +05:30
Lakhan Samani
7d1272d815 fix: update scope for apple login 2022-06-14 14:41:31 +05:30
Lakhan Samani
c9ba0b13f8 fix: update scope for apple login 2022-06-14 13:37:05 +05:30
5 changed files with 1556 additions and 1557 deletions

3020
app/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,29 @@
{ {
"name": "app", "name": "app",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "rm -rf build && NODE_ENV=production node ./esbuild.config.js", "build": "rm -rf build && NODE_ENV=production node ./esbuild.config.js",
"start": "NODE_ENV=development node ./esbuild.config.js" "start": "NODE_ENV=development node ./esbuild.config.js"
}, },
"keywords": [], "keywords": [],
"author": "Lakhan Samani", "author": "Lakhan Samani",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@authorizerdev/authorizer-react": "^0.24.0-beta.1", "@authorizerdev/authorizer-react": "^0.24.0",
"@types/react": "^17.0.15", "@types/react": "^17.0.15",
"@types/react-dom": "^17.0.9", "@types/react-dom": "^17.0.9",
"esbuild": "^0.12.17", "esbuild": "^0.12.17",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-is": "^17.0.2", "react-is": "^17.0.2",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"typescript": "^4.3.5", "typescript": "^4.3.5",
"styled-components": "^5.3.0" "styled-components": "^5.3.0"
}, },
"devDependencies": { "devDependencies": {
"@types/react-router-dom": "^5.1.8", "@types/react-router-dom": "^5.1.8",
"@types/styled-components": "^5.1.11" "@types/styled-components": "^5.1.11"
} }
} }

View File

@@ -2,6 +2,7 @@ package handlers
import ( import (
"context" "context"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@@ -17,7 +18,6 @@ import (
"github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/constants"
"github.com/authorizerdev/authorizer/server/cookie" "github.com/authorizerdev/authorizer/server/cookie"
"github.com/authorizerdev/authorizer/server/crypto"
"github.com/authorizerdev/authorizer/server/db" "github.com/authorizerdev/authorizer/server/db"
"github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/db/models"
"github.com/authorizerdev/authorizer/server/memorystore" "github.com/authorizerdev/authorizer/server/memorystore"
@@ -225,7 +225,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&") redirectURL = redirectURL + "?" + strings.TrimPrefix(params, "&")
} }
c.Redirect(http.StatusTemporaryRedirect, redirectURL) c.Redirect(http.StatusFound, redirectURL)
} }
} }
@@ -462,8 +462,6 @@ func processAppleUserInfo(code string) (models.User, error) {
return user, fmt.Errorf("invalid apple exchange code: %s", err.Error()) return user, fmt.Errorf("invalid apple exchange code: %s", err.Error())
} }
fmt.Println("=> token", oauth2Token.AccessToken)
// Extract the ID Token from OAuth2 token. // Extract the ID Token from OAuth2 token.
rawIDToken, ok := oauth2Token.Extra("id_token").(string) rawIDToken, ok := oauth2Token.Extra("id_token").(string)
if !ok { if !ok {
@@ -471,39 +469,39 @@ func processAppleUserInfo(code string) (models.User, error) {
return user, fmt.Errorf("unable to extract id_token") return user, fmt.Errorf("unable to extract id_token")
} }
fmt.Println("=> rawIDToken", rawIDToken)
tokenSplit := strings.Split(rawIDToken, ".") tokenSplit := strings.Split(rawIDToken, ".")
claimsData := tokenSplit[1] claimsData := tokenSplit[1]
decodedClaimsData, err := crypto.DecryptB64(claimsData) decodedClaimsData, err := base64.RawURLEncoding.DecodeString(claimsData)
if err != nil { if err != nil {
log.Debug("Failed to decrypt claims data: ", err) log.Debugf("Failed to decrypt claims %s: %s", claimsData, err.Error())
return user, fmt.Errorf("failed to decrypt claims data: %s", err.Error()) return user, fmt.Errorf("failed to decrypt claims data: %s", err.Error())
} }
fmt.Println("=> decoded claims data", decodedClaimsData)
claims := make(map[string]interface{}) claims := make(map[string]interface{})
err = json.Unmarshal([]byte(decodedClaimsData), &claims) err = json.Unmarshal(decodedClaimsData, &claims)
if err != nil { if err != nil {
log.Debug("Failed to unmarshal claims data: ", err) log.Debug("Failed to unmarshal claims data: ", err)
return user, fmt.Errorf("failed to unmarshal claims data: %s", err.Error()) return user, fmt.Errorf("failed to unmarshal claims data: %s", err.Error())
} }
fmt.Println("=> claims", claims)
if val, ok := claims["email"]; !ok { if val, ok := claims["email"]; !ok {
log.Debug("Failed to extract email from claims") log.Debug("Failed to extract email from claims.")
return user, fmt.Errorf("unable to extract email") return user, fmt.Errorf("unable to extract email, please check the scopes enabled for your app. It needs `email`, `name` scopes")
} else { } else {
user.Email = val.(string) user.Email = val.(string)
} }
if val, ok := claims["name"]; ok { if val, ok := claims["name"]; ok {
nameData := val.(map[string]interface{}) nameData := val.(map[string]interface{})
givenName := nameData["firstName"].(string) if nameVal, ok := nameData["firstName"]; ok {
familyName := nameData["lastName"].(string) givenName := nameVal.(string)
user.GivenName = &givenName user.GivenName = &givenName
user.FamilyName = &familyName }
if nameVal, ok := nameData["lastName"]; ok {
familyName := nameVal.(string)
user.FamilyName = &familyName
}
} }
return user, err return user, err

View File

@@ -184,7 +184,9 @@ func OAuthLoginHandler() gin.HandlerFunc {
return return
} }
oauth.OAuthProviders.AppleConfig.RedirectURL = hostname + "/oauth_callback/" + constants.SignupMethodApple oauth.OAuthProviders.AppleConfig.RedirectURL = hostname + "/oauth_callback/" + constants.SignupMethodApple
url := oauth.OAuthProviders.AppleConfig.AuthCodeURL(oauthStateString, oauth2.SetAuthURLParam("response_mode", "form_post")) // there is scope encoding issue with oauth2 and how apple expects, hence added scope manually
// check: https://github.com/golang/oauth2/issues/449
url := oauth.OAuthProviders.AppleConfig.AuthCodeURL(oauthStateString, oauth2.SetAuthURLParam("response_mode", "form_post")) + "&scope=name email"
c.Redirect(http.StatusTemporaryRedirect, url) c.Redirect(http.StatusTemporaryRedirect, url)
default: default:
log.Debug("Invalid oauth provider: ", provider) log.Debug("Invalid oauth provider: ", provider)

View File

@@ -130,7 +130,6 @@ func InitOAuth() error {
AuthURL: "https://appleid.apple.com/auth/authorize", AuthURL: "https://appleid.apple.com/auth/authorize",
TokenURL: "https://appleid.apple.com/auth/token", TokenURL: "https://appleid.apple.com/auth/token",
}, },
Scopes: []string{"openid", "name", "email"},
} }
} }