Skip to content

Commit 75a547c

Browse files
committed
fix: other auth recipes for oidc idp + remove logs
1 parent 579899c commit 75a547c

File tree

12 files changed

+248
-117
lines changed

12 files changed

+248
-117
lines changed

app/src/Root.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ export default function Root({
5757
urlProps.redirect_uri = urlProps.redirectURL;
5858

5959
useEffect(() => {
60-
console.log(config);
6160
if (token) {
6261
let redirectURL = config.redirectURL || '/app';
6362
let params = `access_token=${token.access_token}&id_token=${token.id_token}&expires_in=${token.expires_in}&state=${globalState.state}`;
@@ -113,7 +112,7 @@ export default function Root({
113112
<Route path="/app" exact>
114113
<Login urlProps={urlProps} />
115114
</Route>
116-
<Route path="/app/signup" exact>
115+
<Route path="/app/signup">
117116
<SignUp urlProps={urlProps} />
118117
</Route>
119118
<Route path="/app/reset-password">

server/graph/generated/generated.go

Lines changed: 39 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/graph/model/models_gen.go

Lines changed: 8 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/handlers/authorize.go

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ import (
4545
"github.com/authorizerdev/authorizer/server/cookie"
4646
"github.com/authorizerdev/authorizer/server/db"
4747
"github.com/authorizerdev/authorizer/server/memorystore"
48-
"github.com/authorizerdev/authorizer/server/parsers"
4948
"github.com/authorizerdev/authorizer/server/token"
50-
"github.com/authorizerdev/authorizer/server/utils"
5149
)
5250

5351
// Check the flow for generating and verifying codes: https://developer.okta.com/blog/2019/08/22/okta-authjs-pkce#:~:text=PKCE%20works%20by%20having%20the,is%20called%20the%20Code%20Challenge.
@@ -108,19 +106,11 @@ func AuthorizeHandler() gin.HandlerFunc {
108106
}
109107

110108
log := log.WithFields(log.Fields{
111-
"response_mode": responseMode,
112-
"response_type": responseType,
113-
"state": state,
114-
"code_challenge": codeChallenge,
115-
"scope": scope,
116-
"redirect_uri": redirectURI,
117-
"nonce": nonce,
118-
"code": code,
109+
"response_mode": responseMode,
110+
"response_type": responseType,
119111
})
120112

121-
// memorystore.Provider.SetState(codeChallenge, code)
122113
// TODO add state with timeout
123-
124114
// used for response mode query or fragment
125115
loginState := "state=" + state + "&scope=" + strings.Join(scope, " ") + "&redirect_uri=" + redirectURI
126116
if responseType == constants.ResponseTypeCode {
@@ -141,17 +131,6 @@ func AuthorizeHandler() gin.HandlerFunc {
141131
loginURL = "/app#" + loginState
142132
}
143133

144-
if state == "" {
145-
handleResponse(gc, responseMode, loginURL, redirectURI, map[string]interface{}{
146-
"type": "authorization_response",
147-
"response": map[string]interface{}{
148-
"error": "state_required",
149-
"error_description": "state is required",
150-
},
151-
}, http.StatusOK)
152-
return
153-
}
154-
155134
if responseType == constants.ResponseTypeCode && codeChallenge == "" {
156135
handleResponse(gc, responseMode, loginURL, redirectURI, map[string]interface{}{
157136
"type": "authorization_response",
@@ -275,7 +254,6 @@ func AuthorizeHandler() gin.HandlerFunc {
275254
}
276255

277256
if responseType == constants.ResponseTypeToken || responseType == constants.ResponseTypeIDToken {
278-
hostname := parsers.GetHost(gc)
279257
// rollover the session for security
280258
authToken, err := token.CreateAuthToken(gc, user, claims.Roles, scope, claims.LoginMethod, nonce, "")
281259
if err != nil {
@@ -299,7 +277,7 @@ func AuthorizeHandler() gin.HandlerFunc {
299277
cookie.SetSession(gc, authToken.FingerPrintHash)
300278

301279
// used of query mode
302-
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(authToken.IDToken.ExpiresAt, 10) + "&state=" + state + "&id_token=" + authToken.IDToken.Token + "&code=" + code
280+
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(authToken.IDToken.ExpiresAt, 10) + "&state=" + state + "&id_token=" + authToken.IDToken.Token
303281

304282
res := map[string]interface{}{
305283
"access_token": authToken.AccessToken.Token,
@@ -308,19 +286,17 @@ func AuthorizeHandler() gin.HandlerFunc {
308286
"scope": scope,
309287
"token_type": "Bearer",
310288
"expires_in": authToken.AccessToken.ExpiresAt,
311-
"code": code,
312289
}
313290

314-
if utils.StringSliceContains(scope, "offline_access") {
315-
refreshToken, _, err := token.CreateRefreshToken(user, claims.Roles, scope, hostname, nonce, claims.LoginMethod)
316-
if err != nil {
317-
log.Debug("SetUserSession failed: ", err)
318-
handleResponse(gc, responseMode, loginURL, redirectURI, loginError, http.StatusOK)
319-
return
320-
}
321-
res["refresh_token"] = refreshToken
322-
params += "&refresh_token=" + refreshToken
323-
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+nonce, refreshToken)
291+
if nonce != "" {
292+
params += "&nonce=" + nonce
293+
res["nonce"] = nonce
294+
}
295+
296+
if authToken.RefreshToken != nil {
297+
res["refresh_token"] = authToken.RefreshToken.Token
298+
params += "&refresh_token=" + authToken.RefreshToken.Token
299+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
324300
}
325301

326302
if responseMode == constants.ResponseModeQuery {
@@ -349,6 +325,9 @@ func AuthorizeHandler() gin.HandlerFunc {
349325
}
350326

351327
func validateAuthorizeRequest(responseType, responseMode, clientID, state, codeChallenge string) error {
328+
if strings.TrimSpace(state) == "" {
329+
return fmt.Errorf("invalid state. state is required to prevent csrf attack", responseMode)
330+
}
352331
if responseType != constants.ResponseTypeCode && responseType != constants.ResponseTypeToken && responseType != constants.ResponseTypeIDToken {
353332
return fmt.Errorf("invalid response type %s. 'code' & 'token' are valid response_type", responseMode)
354333
}
@@ -387,8 +366,6 @@ func handleResponse(gc *gin.Context, responseMode, loginURI, redirectURI string,
387366
})
388367
return
389368
case constants.ResponseModeFormPost:
390-
fmt.Println("=> trying tof orm post")
391-
fmt.Printf("=> %+v \n", data["response"])
392369
gc.HTML(httpStatusCode, authorizeFormPostTemplate, gin.H{
393370
"target_origin": redirectURI,
394371
"authorization_response": data["response"],

server/handlers/oauth_callback.go

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,20 @@ func OAuthCallbackHandler() gin.HandlerFunc {
5656
scopes := strings.Split(sessionSplit[3], ",")
5757

5858
user := models.User{}
59-
code := ctx.Request.FormValue("code")
59+
oauthCode := ctx.Request.FormValue("code")
6060
switch provider {
6161
case constants.AuthRecipeMethodGoogle:
62-
user, err = processGoogleUserInfo(code)
62+
user, err = processGoogleUserInfo(oauthCode)
6363
case constants.AuthRecipeMethodGithub:
64-
user, err = processGithubUserInfo(code)
64+
user, err = processGithubUserInfo(oauthCode)
6565
case constants.AuthRecipeMethodFacebook:
66-
user, err = processFacebookUserInfo(code)
66+
user, err = processFacebookUserInfo(oauthCode)
6767
case constants.AuthRecipeMethodLinkedIn:
68-
user, err = processLinkedInUserInfo(code)
68+
user, err = processLinkedInUserInfo(oauthCode)
6969
case constants.AuthRecipeMethodApple:
70-
user, err = processAppleUserInfo(code)
70+
user, err = processAppleUserInfo(oauthCode)
7171
case constants.AuthRecipeMethodTwitter:
72-
user, err = processTwitterUserInfo(code, sessionState)
72+
user, err = processTwitterUserInfo(oauthCode, sessionState)
7373
default:
7474
log.Info("Invalid oauth provider")
7575
err = fmt.Errorf(`invalid oauth provider`)
@@ -200,27 +200,58 @@ func OAuthCallbackHandler() gin.HandlerFunc {
200200
// TODO
201201
// use stateValue to get code / nonce
202202
// add code / nonce to id_token
203-
nonce := uuid.New().String()
204-
authToken, err := token.CreateAuthToken(ctx, user, inputRoles, scopes, provider, nonce, "")
203+
code := ""
204+
codeChallenge := ""
205+
nonce := ""
206+
if stateValue != "" {
207+
// Get state from store
208+
authorizeState, _ := memorystore.Provider.GetState(stateValue)
209+
if authorizeState != "" {
210+
authorizeStateSplit := strings.Split(authorizeState, "@@")
211+
if len(authorizeStateSplit) > 1 {
212+
code = authorizeStateSplit[0]
213+
codeChallenge = authorizeStateSplit[1]
214+
} else {
215+
nonce = authorizeState
216+
}
217+
go memorystore.Provider.RemoveState(stateValue)
218+
}
219+
}
220+
if nonce == "" {
221+
nonce = uuid.New().String()
222+
}
223+
authToken, err := token.CreateAuthToken(ctx, user, inputRoles, scopes, provider, nonce, code)
205224
if err != nil {
206225
log.Debug("Failed to create auth token: ", err)
207226
ctx.JSON(500, gin.H{"error": err.Error()})
208227
}
209228

229+
// Code challenge could be optional if PKCE flow is not used
230+
if code != "" {
231+
if err := memorystore.Provider.SetState(code, codeChallenge+"@@"+authToken.FingerPrintHash); err != nil {
232+
log.Debug("SetState failed: ", err)
233+
ctx.JSON(500, gin.H{"error": err.Error()})
234+
}
235+
}
236+
210237
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
211238
if expiresIn <= 0 {
212239
expiresIn = 1
213240
}
214241

215-
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + stateValue + "&id_token=" + authToken.IDToken.Token
242+
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + stateValue + "&id_token=" + authToken.IDToken.Token + "&nonce=" + nonce
243+
244+
if code != "" {
245+
params += "&code=" + code
246+
}
216247

217248
sessionKey := provider + ":" + user.ID
218249
cookie.SetSession(ctx, authToken.FingerPrintHash)
219250
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
220251
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
221252

222253
if authToken.RefreshToken != nil {
223-
params = params + `&refresh_token=` + authToken.RefreshToken.Token
254+
params += `&refresh_token=` + authToken.RefreshToken.Token
224255
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
225256
}
226257

0 commit comments

Comments
 (0)