Compare commits

...

10 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
4 changed files with 1554 additions and 1555 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,26 +469,21 @@ 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, please check the scopes enabled for your app. It needs `email`, `name` scopes") return user, fmt.Errorf("unable to extract email, please check the scopes enabled for your app. It needs `email`, `name` scopes")
@@ -500,10 +493,15 @@ func processAppleUserInfo(code string) (models.User, error) {
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,8 +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
// Scope from the root config was not passed for apple login // there is scope encoding issue with oauth2 and how apple expects, hence added scope manually
url := oauth.OAuthProviders.AppleConfig.AuthCodeURL(oauthStateString, oauth2.SetAuthURLParam("response_mode", "form_post"), oauth2.SetAuthURLParam("scope", "name email")) // 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)