Skip to content

Commit a8f9e1d

Browse files
committed
feat(auth): implement RevokeToken endpoint
1 parent d86dcb3 commit a8f9e1d

File tree

2 files changed

+501
-0
lines changed

2 files changed

+501
-0
lines changed

httpapi/auth/revoke.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package authservice
2+
3+
import (
4+
"errors"
5+
"net/http"
6+
7+
"github.com/database-playground/backend-v2/internal/auth"
8+
"github.com/gin-gonic/gin"
9+
)
10+
11+
// RevokeToken implements OAuth 2.0 Token Revocation (RFC 7009)
12+
// POST /api/auth/v2/revoke
13+
func (s *AuthService) RevokeToken(c *gin.Context) {
14+
// Parse form data
15+
token := c.PostForm("token")
16+
tokenTypeHint := c.PostForm("token_type_hint")
17+
18+
// Validate required parameters
19+
if token == "" {
20+
c.JSON(http.StatusBadRequest, gin.H{
21+
"error": "invalid_request",
22+
"error_description": "Missing required parameter: token",
23+
})
24+
return
25+
}
26+
27+
// Validate token_type_hint if provided
28+
if tokenTypeHint != "" && tokenTypeHint != "access_token" {
29+
c.JSON(http.StatusBadRequest, gin.H{
30+
"error": "unsupported_token_type",
31+
"error_description": "Only access_token is supported for token_type_hint",
32+
})
33+
return
34+
}
35+
36+
// Attempt to revoke the token
37+
err := s.storage.Delete(c.Request.Context(), token)
38+
if err != nil && !errors.Is(err, auth.ErrNotFound) {
39+
// Internal server error - failed to revoke token
40+
c.JSON(http.StatusInternalServerError, gin.H{
41+
"error": "server_error",
42+
"error_description": "Failed to revoke the token. Please try again later.",
43+
})
44+
return
45+
}
46+
47+
// Success - return 200 OK regardless of whether token existed
48+
// This is per RFC 7009 section 2: "The client must not use the token again after revocation."
49+
// "The authorization server responds with HTTP status code 200 if the revocation is successful"
50+
c.Status(http.StatusOK)
51+
}

0 commit comments

Comments
 (0)