summaryrefslogtreecommitdiff
path: root/internal/oauth/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/oauth/server.go')
-rw-r--r--internal/oauth/server.go74
1 files changed, 74 insertions, 0 deletions
diff --git a/internal/oauth/server.go b/internal/oauth/server.go
index c0c3c329c..0bc7a3b01 100644
--- a/internal/oauth/server.go
+++ b/internal/oauth/server.go
@@ -24,6 +24,7 @@ import (
"net/http"
"strings"
+ errorsv2 "codeberg.org/gruf/go-errors/v2"
"codeberg.org/superseriousbusiness/oauth2/v4"
oautherr "codeberg.org/superseriousbusiness/oauth2/v4/errors"
"codeberg.org/superseriousbusiness/oauth2/v4/manage"
@@ -71,6 +72,7 @@ type Server interface {
ValidationBearerToken(r *http.Request) (oauth2.TokenInfo, error)
GenerateUserAccessToken(ctx context.Context, ti oauth2.TokenInfo, clientSecret string, userID string) (accessToken oauth2.TokenInfo, err error)
LoadAccessToken(ctx context.Context, access string) (accessToken oauth2.TokenInfo, err error)
+ RevokeAccessToken(ctx context.Context, clientID string, clientSecret string, access string) gtserror.WithCode
}
// s fulfils the Server interface
@@ -338,3 +340,75 @@ func (s *s) GenerateUserAccessToken(ctx context.Context, ti oauth2.TokenInfo, cl
func (s *s) LoadAccessToken(ctx context.Context, access string) (accessToken oauth2.TokenInfo, err error) {
return s.server.Manager.LoadAccessToken(ctx, access)
}
+
+func (s *s) RevokeAccessToken(
+ ctx context.Context,
+ clientID string,
+ clientSecret string,
+ access string,
+) gtserror.WithCode {
+ token, err := s.server.Manager.LoadAccessToken(ctx, access)
+ switch {
+ case err == nil:
+ // Got the token, can
+ // proceed to invalidate.
+
+ case errorsv2.IsV2(
+ err,
+ db.ErrNoEntries,
+ oautherr.ErrExpiredAccessToken,
+ ):
+ // Token already deleted, expired,
+ // or doesn't exist, nothing to do.
+ return nil
+
+ default:
+ // Real error.
+ log.Errorf(ctx, "db error loading access token: %v", err)
+ return gtserror.NewErrorInternalError(
+ oautherr.ErrServerError,
+ "db error loading access token, check logs",
+ )
+ }
+
+ // Ensure token's client ID matches provided client ID.
+ if token.GetClientID() != clientID {
+ log.Debug(ctx, "client id of token does not match provided client_id")
+ return gtserror.NewErrorForbidden(
+ oautherr.ErrUnauthorizedClient,
+ "You are not authorized to revoke this token",
+ )
+ }
+
+ // Get client from the db using provided client ID.
+ client, err := s.server.Manager.GetClient(ctx, clientID)
+ if err != nil {
+ log.Errorf(ctx, "db error loading client: %v", err)
+ return gtserror.NewErrorInternalError(
+ oautherr.ErrServerError,
+ "db error loading client, check logs",
+ )
+ }
+
+ // Ensure requester also knows the client secret,
+ // which confirms that they indeed created the client.
+ if client.GetSecret() != clientSecret {
+ log.Debug(ctx, "secret of client does not match provided client_secret")
+ return gtserror.NewErrorForbidden(
+ oautherr.ErrUnauthorizedClient,
+ "You are not authorized to revoke this token",
+ )
+ }
+
+ // All good, invalidate the token.
+ err = s.server.Manager.RemoveAccessToken(ctx, access)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ log.Errorf(ctx, "db error removing access token: %v", err)
+ return gtserror.NewErrorInternalError(
+ oautherr.ErrServerError,
+ "db error removing access token, check logs",
+ )
+ }
+
+ return nil
+}