Skip to content

Commit 8c27f20

Browse files
authored
Merge pull request #193 from authorizerdev/fix/invalidate-session-token
fix: add provider to token creation
2 parents 64d64b4 + 29c6003 commit 8c27f20

27 files changed

+368
-158
lines changed

server/constants/auth_methods.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package constants
2+
3+
const (
4+
// AuthRecipeMethodBasicAuth is the basic_auth auth method
5+
AuthRecipeMethodBasicAuth = "basic_auth"
6+
// AuthRecipeMethodMagicLinkLogin is the magic_link_login auth method
7+
AuthRecipeMethodMagicLinkLogin = "magic_link_login"
8+
// AuthRecipeMethodGoogle is the google auth method
9+
AuthRecipeMethodGoogle = "google"
10+
// AuthRecipeMethodGithub is the github auth method
11+
AuthRecipeMethodGithub = "github"
12+
// AuthRecipeMethodFacebook is the facebook auth method
13+
AuthRecipeMethodFacebook = "facebook"
14+
// AuthRecipeMethodLinkedin is the linkedin auth method
15+
AuthRecipeMethodLinkedIn = "linkedin"
16+
// AuthRecipeMethodApple is the apple auth method
17+
AuthRecipeMethodApple = "apple"
18+
)

server/constants/signup_methods.go

Lines changed: 0 additions & 18 deletions
This file was deleted.

server/handlers/authorize.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,18 @@ func AuthorizeHandler() gin.HandlerFunc {
218218
return
219219
}
220220

221+
sessionKey := user.ID
222+
if claims.LoginMethod != "" {
223+
sessionKey = claims.LoginMethod + ":" + user.ID
224+
}
225+
221226
// if user is logged in
222-
// based on the response type, generate the response
227+
// based on the response type code, generate the response
223228
if isResponseTypeCode {
224229
// rollover the session for security
225-
go memorystore.Provider.DeleteUserSession(user.ID, claims.Nonce)
230+
go memorystore.Provider.DeleteUserSession(sessionKey, claims.Nonce)
226231
nonce := uuid.New().String()
227-
newSessionTokenData, newSessionToken, err := token.CreateSessionToken(user, nonce, claims.Roles, scope)
232+
newSessionTokenData, newSessionToken, err := token.CreateSessionToken(user, nonce, claims.Roles, scope, claims.LoginMethod)
228233
if err != nil {
229234
if isQuery {
230235
gc.Redirect(http.StatusFound, loginURL)
@@ -262,7 +267,7 @@ func AuthorizeHandler() gin.HandlerFunc {
262267

263268
if isResponseTypeToken {
264269
// rollover the session for security
265-
authToken, err := token.CreateAuthToken(gc, user, claims.Roles, scope)
270+
authToken, err := token.CreateAuthToken(gc, user, claims.Roles, scope, claims.LoginMethod)
266271
if err != nil {
267272
if isQuery {
268273
gc.Redirect(http.StatusFound, loginURL)
@@ -280,9 +285,10 @@ func AuthorizeHandler() gin.HandlerFunc {
280285
}
281286
return
282287
}
283-
go memorystore.Provider.DeleteUserSession(user.ID, claims.Nonce)
284-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
285-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
288+
289+
go memorystore.Provider.DeleteUserSession(sessionKey, claims.Nonce)
290+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
291+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
286292
cookie.SetSession(gc, authToken.FingerPrintHash)
287293

288294
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
@@ -305,7 +311,7 @@ func AuthorizeHandler() gin.HandlerFunc {
305311
if authToken.RefreshToken != nil {
306312
res["refresh_token"] = authToken.RefreshToken.Token
307313
params += "&refresh_token=" + authToken.RefreshToken.Token
308-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
314+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
309315
}
310316

311317
if isQuery {

server/handlers/oauth_callback.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ func OAuthCallbackHandler() gin.HandlerFunc {
5757
user := models.User{}
5858
code := c.Request.FormValue("code")
5959
switch provider {
60-
case constants.SignupMethodGoogle:
60+
case constants.AuthRecipeMethodGoogle:
6161
user, err = processGoogleUserInfo(code)
62-
case constants.SignupMethodGithub:
62+
case constants.AuthRecipeMethodGithub:
6363
user, err = processGithubUserInfo(code)
64-
case constants.SignupMethodFacebook:
64+
case constants.AuthRecipeMethodFacebook:
6565
user, err = processFacebookUserInfo(code)
66-
case constants.SignupMethodLinkedIn:
66+
case constants.AuthRecipeMethodLinkedIn:
6767
user, err = processLinkedInUserInfo(code)
68-
case constants.SignupMethodApple:
68+
case constants.AuthRecipeMethodApple:
6969
user, err = processAppleUserInfo(code)
7070
default:
7171
log.Info("Invalid oauth provider")
@@ -192,7 +192,7 @@ func OAuthCallbackHandler() gin.HandlerFunc {
192192
}
193193
}
194194

195-
authToken, err := token.CreateAuthToken(c, user, inputRoles, scopes)
195+
authToken, err := token.CreateAuthToken(c, user, inputRoles, scopes, provider)
196196
if err != nil {
197197
log.Debug("Failed to create auth token: ", err)
198198
c.JSON(500, gin.H{"error": err.Error()})
@@ -205,13 +205,14 @@ func OAuthCallbackHandler() gin.HandlerFunc {
205205

206206
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + stateValue + "&id_token=" + authToken.IDToken.Token
207207

208+
sessionKey := provider + ":" + user.ID
208209
cookie.SetSession(c, authToken.FingerPrintHash)
209-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
210-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
210+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
211+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
211212

212213
if authToken.RefreshToken != nil {
213214
params = params + `&refresh_token=` + authToken.RefreshToken.Token
214-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
215+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
215216
}
216217

217218
go db.Provider.AddSession(models.Session{

server/handlers/oauth_login.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ func OAuthLoginHandler() gin.HandlerFunc {
100100
provider := c.Param("oauth_provider")
101101
isProviderConfigured := true
102102
switch provider {
103-
case constants.SignupMethodGoogle:
103+
case constants.AuthRecipeMethodGoogle:
104104
if oauth.OAuthProviders.GoogleConfig == nil {
105105
log.Debug("Google OAuth provider is not configured")
106106
isProviderConfigured = false
107107
break
108108
}
109-
err := memorystore.Provider.SetState(oauthStateString, constants.SignupMethodGoogle)
109+
err := memorystore.Provider.SetState(oauthStateString, constants.AuthRecipeMethodGoogle)
110110
if err != nil {
111111
log.Debug("Error setting state: ", err)
112112
c.JSON(500, gin.H{
@@ -115,75 +115,75 @@ func OAuthLoginHandler() gin.HandlerFunc {
115115
return
116116
}
117117
// during the init of OAuthProvider authorizer url might be empty
118-
oauth.OAuthProviders.GoogleConfig.RedirectURL = hostname + "/oauth_callback/" + constants.SignupMethodGoogle
118+
oauth.OAuthProviders.GoogleConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodGoogle
119119
url := oauth.OAuthProviders.GoogleConfig.AuthCodeURL(oauthStateString)
120120
c.Redirect(http.StatusTemporaryRedirect, url)
121-
case constants.SignupMethodGithub:
121+
case constants.AuthRecipeMethodGithub:
122122
if oauth.OAuthProviders.GithubConfig == nil {
123123
log.Debug("Github OAuth provider is not configured")
124124
isProviderConfigured = false
125125
break
126126
}
127-
err := memorystore.Provider.SetState(oauthStateString, constants.SignupMethodGithub)
127+
err := memorystore.Provider.SetState(oauthStateString, constants.AuthRecipeMethodGithub)
128128
if err != nil {
129129
log.Debug("Error setting state: ", err)
130130
c.JSON(500, gin.H{
131131
"error": "internal server error",
132132
})
133133
return
134134
}
135-
oauth.OAuthProviders.GithubConfig.RedirectURL = hostname + "/oauth_callback/" + constants.SignupMethodGithub
135+
oauth.OAuthProviders.GithubConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodGithub
136136
url := oauth.OAuthProviders.GithubConfig.AuthCodeURL(oauthStateString)
137137
c.Redirect(http.StatusTemporaryRedirect, url)
138-
case constants.SignupMethodFacebook:
138+
case constants.AuthRecipeMethodFacebook:
139139
if oauth.OAuthProviders.FacebookConfig == nil {
140140
log.Debug("Facebook OAuth provider is not configured")
141141
isProviderConfigured = false
142142
break
143143
}
144-
err := memorystore.Provider.SetState(oauthStateString, constants.SignupMethodFacebook)
144+
err := memorystore.Provider.SetState(oauthStateString, constants.AuthRecipeMethodFacebook)
145145
if err != nil {
146146
log.Debug("Error setting state: ", err)
147147
c.JSON(500, gin.H{
148148
"error": "internal server error",
149149
})
150150
return
151151
}
152-
oauth.OAuthProviders.FacebookConfig.RedirectURL = hostname + "/oauth_callback/" + constants.SignupMethodFacebook
152+
oauth.OAuthProviders.FacebookConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodFacebook
153153
url := oauth.OAuthProviders.FacebookConfig.AuthCodeURL(oauthStateString)
154154
c.Redirect(http.StatusTemporaryRedirect, url)
155-
case constants.SignupMethodLinkedIn:
155+
case constants.AuthRecipeMethodLinkedIn:
156156
if oauth.OAuthProviders.LinkedInConfig == nil {
157157
log.Debug("Linkedin OAuth provider is not configured")
158158
isProviderConfigured = false
159159
break
160160
}
161-
err := memorystore.Provider.SetState(oauthStateString, constants.SignupMethodLinkedIn)
161+
err := memorystore.Provider.SetState(oauthStateString, constants.AuthRecipeMethodLinkedIn)
162162
if err != nil {
163163
log.Debug("Error setting state: ", err)
164164
c.JSON(500, gin.H{
165165
"error": "internal server error",
166166
})
167167
return
168168
}
169-
oauth.OAuthProviders.LinkedInConfig.RedirectURL = hostname + "/oauth_callback/" + constants.SignupMethodLinkedIn
169+
oauth.OAuthProviders.LinkedInConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodLinkedIn
170170
url := oauth.OAuthProviders.LinkedInConfig.AuthCodeURL(oauthStateString)
171171
c.Redirect(http.StatusTemporaryRedirect, url)
172-
case constants.SignupMethodApple:
172+
case constants.AuthRecipeMethodApple:
173173
if oauth.OAuthProviders.AppleConfig == nil {
174174
log.Debug("Apple OAuth provider is not configured")
175175
isProviderConfigured = false
176176
break
177177
}
178-
err := memorystore.Provider.SetState(oauthStateString, constants.SignupMethodApple)
178+
err := memorystore.Provider.SetState(oauthStateString, constants.AuthRecipeMethodApple)
179179
if err != nil {
180180
log.Debug("Error setting state: ", err)
181181
c.JSON(500, gin.H{
182182
"error": "internal server error",
183183
})
184184
return
185185
}
186-
oauth.OAuthProviders.AppleConfig.RedirectURL = hostname + "/oauth_callback/" + constants.SignupMethodApple
186+
oauth.OAuthProviders.AppleConfig.RedirectURL = hostname + "/oauth_callback/" + constants.AuthRecipeMethodApple
187187
// there is scope encoding issue with oauth2 and how apple expects, hence added scope manually
188188
// check: https://github.com/golang/oauth2/issues/449
189189
url := oauth.OAuthProviders.AppleConfig.AuthCodeURL(oauthStateString, oauth2.SetAuthURLParam("response_mode", "form_post")) + "&scope=name email"

server/handlers/revoke.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,14 @@ func RevokeHandler() gin.HandlerFunc {
5656
return
5757
}
5858

59-
memorystore.Provider.DeleteUserSession(claims["sub"].(string), claims["nonce"].(string))
59+
userID := claims["sub"].(string)
60+
loginMethod := claims["login_method"]
61+
sessionToken := userID
62+
if loginMethod != nil && loginMethod != "" {
63+
sessionToken = loginMethod.(string) + ":" + userID
64+
}
65+
66+
memorystore.Provider.DeleteUserSession(sessionToken, claims["nonce"].(string))
6067

6168
gc.JSON(http.StatusOK, gin.H{
6269
"message": "Token revoked successfully",

server/handlers/token.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ func TokenHandler() gin.HandlerFunc {
7272

7373
var userID string
7474
var roles, scope []string
75+
loginMethod := ""
76+
sessionKey := ""
77+
7578
if isAuthorizationCodeGrant {
7679

7780
if codeVerifier == "" {
@@ -134,8 +137,13 @@ func TokenHandler() gin.HandlerFunc {
134137
userID = claims.Subject
135138
roles = claims.Roles
136139
scope = claims.Scope
140+
loginMethod = claims.LoginMethod
137141
// rollover the session for security
138-
go memorystore.Provider.DeleteUserSession(userID, claims.Nonce)
142+
sessionKey = userID
143+
if loginMethod != "" {
144+
sessionKey = loginMethod + ":" + userID
145+
}
146+
go memorystore.Provider.DeleteUserSession(sessionKey, claims.Nonce)
139147
} else {
140148
// validate refresh token
141149
if refreshToken == "" {
@@ -155,6 +163,7 @@ func TokenHandler() gin.HandlerFunc {
155163
})
156164
}
157165
userID = claims["sub"].(string)
166+
loginMethod := claims["login_method"]
158167
rolesInterface := claims["roles"].([]interface{})
159168
scopeInterface := claims["scope"].([]interface{})
160169
for _, v := range rolesInterface {
@@ -163,8 +172,22 @@ func TokenHandler() gin.HandlerFunc {
163172
for _, v := range scopeInterface {
164173
scope = append(scope, v.(string))
165174
}
175+
176+
sessionKey = userID
177+
if loginMethod != nil && loginMethod != "" {
178+
sessionKey = loginMethod.(string) + ":" + sessionKey
179+
}
166180
// remove older refresh token and rotate it for security
167-
go memorystore.Provider.DeleteUserSession(userID, claims["nonce"].(string))
181+
go memorystore.Provider.DeleteUserSession(sessionKey, claims["nonce"].(string))
182+
}
183+
184+
if sessionKey == "" {
185+
log.Debug("Error getting sessionKey: ", sessionKey, loginMethod)
186+
gc.JSON(http.StatusUnauthorized, gin.H{
187+
"error": "unauthorized",
188+
"error_description": "User not found",
189+
})
190+
return
168191
}
169192

170193
user, err := db.Provider.GetUserByID(userID)
@@ -177,7 +200,7 @@ func TokenHandler() gin.HandlerFunc {
177200
return
178201
}
179202

180-
authToken, err := token.CreateAuthToken(gc, user, roles, scope)
203+
authToken, err := token.CreateAuthToken(gc, user, roles, scope, loginMethod)
181204
if err != nil {
182205
log.Debug("Error creating auth token: ", err)
183206
gc.JSON(http.StatusUnauthorized, gin.H{
@@ -186,8 +209,8 @@ func TokenHandler() gin.HandlerFunc {
186209
})
187210
return
188211
}
189-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
190-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
212+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
213+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
191214
cookie.SetSession(gc, authToken.FingerPrintHash)
192215

193216
expiresIn := authToken.AccessToken.ExpiresAt - time.Now().Unix()
@@ -205,7 +228,7 @@ func TokenHandler() gin.HandlerFunc {
205228

206229
if authToken.RefreshToken != nil {
207230
res["refresh_token"] = authToken.RefreshToken.Token
208-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
231+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
209232
}
210233

211234
gc.JSON(http.StatusOK, res)

server/handlers/verify_email.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,11 @@ func VerifyEmailHandler() gin.HandlerFunc {
9292
} else {
9393
scope = strings.Split(scopeString, " ")
9494
}
95-
authToken, err := token.CreateAuthToken(c, user, roles, scope)
95+
loginMethod := constants.AuthRecipeMethodBasicAuth
96+
if verificationRequest.Identifier == constants.VerificationTypeMagicLinkLogin {
97+
loginMethod = constants.AuthRecipeMethodMagicLinkLogin
98+
}
99+
authToken, err := token.CreateAuthToken(c, user, roles, scope, loginMethod)
96100
if err != nil {
97101
log.Debug("Error creating auth token: ", err)
98102
errorRes["error_description"] = err.Error()
@@ -107,13 +111,14 @@ func VerifyEmailHandler() gin.HandlerFunc {
107111

108112
params := "access_token=" + authToken.AccessToken.Token + "&token_type=bearer&expires_in=" + strconv.FormatInt(expiresIn, 10) + "&state=" + state + "&id_token=" + authToken.IDToken.Token
109113

114+
sessionKey := loginMethod + ":" + user.ID
110115
cookie.SetSession(c, authToken.FingerPrintHash)
111-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
112-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
116+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeSessionToken+"_"+authToken.FingerPrint, authToken.FingerPrintHash)
117+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeAccessToken+"_"+authToken.FingerPrint, authToken.AccessToken.Token)
113118

114119
if authToken.RefreshToken != nil {
115120
params = params + `&refresh_token=` + authToken.RefreshToken.Token
116-
memorystore.Provider.SetUserSession(user.ID, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
121+
memorystore.Provider.SetUserSession(sessionKey, constants.TokenTypeRefreshToken+"_"+authToken.FingerPrint, authToken.RefreshToken.Token)
117122
}
118123

119124
if redirectURL == "" {

0 commit comments

Comments
 (0)