Skip to content

Commit 3bb90ac

Browse files
committed
feat: add revoke mutation + handler
1 parent a69b8e2 commit 3bb90ac

File tree

9 files changed

+195
-2
lines changed

9 files changed

+195
-2
lines changed

server/graph/generated/generated.go

Lines changed: 109 additions & 0 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: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/graph/schema.graphqls

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ input PaginatedInput {
267267
pagination: PaginationInput
268268
}
269269

270+
input OAuthRevokeInput {
271+
refresh_token: String!
272+
}
273+
270274
type Mutation {
271275
signup(params: SignUpInput!): AuthResponse!
272276
login(params: LoginInput!): AuthResponse!
@@ -277,6 +281,7 @@ type Mutation {
277281
resend_verify_email(params: ResendVerifyEmailInput!): Response!
278282
forgot_password(params: ForgotPasswordInput!): Response!
279283
reset_password(params: ResetPasswordInput!): Response!
284+
revoke(params: OAuthRevokeInput!): Response!
280285
# admin only apis
281286
_delete_user(params: DeleteUserInput!): Response!
282287
_update_user(params: UpdateUserInput!): User!

server/graph/schema.resolvers.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ func (r *mutationResolver) ResetPassword(ctx context.Context, params model.Reset
4747
return resolvers.ResetPasswordResolver(ctx, params)
4848
}
4949

50+
func (r *mutationResolver) Revoke(ctx context.Context, params model.OAuthRevokeInput) (*model.Response, error) {
51+
return resolvers.RevokeResolver(ctx, params)
52+
}
53+
5054
func (r *mutationResolver) DeleteUser(ctx context.Context, params model.DeleteUserInput) (*model.Response, error) {
5155
return resolvers.DeleteUserResolver(ctx, params)
5256
}
@@ -105,5 +109,7 @@ func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResol
105109
// Query returns generated.QueryResolver implementation.
106110
func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
107111

108-
type mutationResolver struct{ *Resolver }
109-
type queryResolver struct{ *Resolver }
112+
type (
113+
mutationResolver struct{ *Resolver }
114+
queryResolver struct{ *Resolver }
115+
)

server/handlers/logout.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/gin-gonic/gin"
1010
)
1111

12+
// Handler to logout user
1213
func LogoutHandler() gin.HandlerFunc {
1314
return func(gc *gin.Context) {
1415
// get fingerprint hash

server/handlers/revoke.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package handlers
2+
3+
import (
4+
"net/http"
5+
"strings"
6+
7+
"github.com/authorizerdev/authorizer/server/constants"
8+
"github.com/authorizerdev/authorizer/server/envstore"
9+
"github.com/authorizerdev/authorizer/server/sessionstore"
10+
"github.com/gin-gonic/gin"
11+
)
12+
13+
// Revoke handler to revoke refresh token
14+
func RevokeHandler() gin.HandlerFunc {
15+
return func(gc *gin.Context) {
16+
var reqBody map[string]string
17+
if err := gc.BindJSON(&reqBody); err != nil {
18+
gc.JSON(http.StatusBadRequest, gin.H{
19+
"error": "error_binding_json",
20+
"error_description": err.Error(),
21+
})
22+
return
23+
}
24+
// get fingerprint hash
25+
refreshToken := strings.TrimSpace(reqBody["refresh_token"])
26+
clientID := strings.TrimSpace(reqBody["client_id"])
27+
28+
if clientID == "" {
29+
gc.JSON(http.StatusBadRequest, gin.H{
30+
"error": "client_id_required",
31+
"error_description": "The client id is required",
32+
})
33+
return
34+
}
35+
36+
if clientID != envstore.EnvStoreObj.GetStringStoreEnvVariable(constants.EnvKeyClientID) {
37+
gc.JSON(http.StatusBadRequest, gin.H{
38+
"error": "invalid_client_id",
39+
"error_description": "The client id is invalid",
40+
})
41+
return
42+
}
43+
44+
sessionstore.RemoveState(refreshToken)
45+
46+
gc.JSON(http.StatusOK, gin.H{
47+
"message": "Token revoked successfully",
48+
})
49+
}
50+
}

server/handlers/token.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/gin-gonic/gin"
1616
)
1717

18+
// TokenHandler to handle /oauth/token requests
1819
// grant type required
1920
func TokenHandler() gin.HandlerFunc {
2021
return func(gc *gin.Context) {

server/resolvers/revoke.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package resolvers
2+
3+
import (
4+
"context"
5+
6+
"github.com/authorizerdev/authorizer/server/graph/model"
7+
"github.com/authorizerdev/authorizer/server/sessionstore"
8+
)
9+
10+
// RevokeResolver resolver to revoke refresh token
11+
func RevokeResolver(ctx context.Context, params model.OAuthRevokeInput) (*model.Response, error) {
12+
sessionstore.RemoveState(params.RefreshToken)
13+
return &model.Response{
14+
Message: "Token revoked",
15+
}, nil
16+
}

server/routes/routes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func InitRouter() *gin.Engine {
2727
router.GET("/userinfo", handlers.UserInfoHandler())
2828
router.GET("/logout", handlers.LogoutHandler())
2929
router.POST("/oauth/token", handlers.TokenHandler())
30+
router.POST("/oauth/revoke", handlers.RevokeHandler())
3031

3132
router.LoadHTMLGlob("templates/*")
3233
// login page app related routes.

0 commit comments

Comments
 (0)