Add OAuth2 API scope registration and enforcement
Register v1 API scopes in coredata, advertise them in OIDC discovery and protected-resource metadata, show them on the consent screen, and enforce scope-to-action mapping in the IAM Authorizer before policy evaluation. Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
@@ -16,7 +16,7 @@ import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/iam"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2server"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2"
|
||||
"go.probo.inc/probo/pkg/mail"
|
||||
"go.probo.inc/probo/pkg/server/api/authn"
|
||||
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
|
||||
@@ -176,7 +176,7 @@ func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error
|
||||
return nil, gqlutils.NotFound(ctx, err)
|
||||
}
|
||||
|
||||
if oauthErr, ok := errors.AsType[*oauth2server.OAuth2Error](err); ok {
|
||||
if oauthErr, ok := errors.AsType[*oauth2.OAuth2Error](err); ok {
|
||||
return nil, gqlutils.Invalidf(ctx, "%s", oauthErr.Description())
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
"go.gearno.de/kit/httpserver"
|
||||
"go.gearno.de/kit/log"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2server"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2"
|
||||
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
|
||||
)
|
||||
|
||||
@@ -35,13 +35,13 @@ func (h *OAuth2Handler) handleAuthorizeError(w http.ResponseWriter, r *http.Requ
|
||||
}
|
||||
|
||||
func (h *OAuth2Handler) renderOAuth2ErrorResponse(w http.ResponseWriter, r *http.Request, err error) {
|
||||
oauthErr, ok := errors.AsType[*oauth2server.OAuth2Error](err)
|
||||
oauthErr, ok := errors.AsType[*oauth2.OAuth2Error](err)
|
||||
if !ok {
|
||||
httpserver.RenderError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
if errors.Is(err, oauth2server.ErrServerError) {
|
||||
if errors.Is(err, oauth2.ErrServerError) {
|
||||
h.logger.ErrorCtx(r.Context(), "oauth2 server error", log.Error(err))
|
||||
}
|
||||
|
||||
@@ -54,15 +54,15 @@ func (h *OAuth2Handler) renderOAuth2ErrorResponse(w http.ResponseWriter, r *http
|
||||
}
|
||||
|
||||
func isRedirectableError(err error) bool {
|
||||
return errors.Is(err, oauth2server.ErrAccessDenied) ||
|
||||
errors.Is(err, oauth2server.ErrInvalidRequest) ||
|
||||
errors.Is(err, oauth2server.ErrInvalidScope) ||
|
||||
errors.Is(err, oauth2server.ErrUnauthorizedClient) ||
|
||||
errors.Is(err, oauth2server.ErrInvalidGrant) ||
|
||||
errors.Is(err, oauth2server.ErrUnsupportedGrantType)
|
||||
return errors.Is(err, oauth2.ErrAccessDenied) ||
|
||||
errors.Is(err, oauth2.ErrInvalidRequest) ||
|
||||
errors.Is(err, oauth2.ErrInvalidScope) ||
|
||||
errors.Is(err, oauth2.ErrUnauthorizedClient) ||
|
||||
errors.Is(err, oauth2.ErrInvalidGrant) ||
|
||||
errors.Is(err, oauth2.ErrUnsupportedGrantType)
|
||||
}
|
||||
|
||||
func oauth2ErrorStatusCode(err *oauth2server.OAuth2Error) int {
|
||||
func oauth2ErrorStatusCode(err *oauth2.OAuth2Error) int {
|
||||
switch err.ErrorCode() {
|
||||
case "access_denied":
|
||||
return http.StatusForbidden
|
||||
@@ -75,22 +75,22 @@ func oauth2ErrorStatusCode(err *oauth2server.OAuth2Error) int {
|
||||
}
|
||||
}
|
||||
|
||||
func toOAuth2Error(err error) *oauth2server.OAuth2Error {
|
||||
func toOAuth2Error(err error) *oauth2.OAuth2Error {
|
||||
switch {
|
||||
case errors.Is(err, oauth2server.ErrClientNotFound):
|
||||
return oauth2server.NewError(oauth2server.ErrInvalidClient, oauth2server.WithDescription("client not found"))
|
||||
case errors.Is(err, oauth2server.ErrInvalidRedirectURI):
|
||||
return oauth2server.ErrInvalidRedirectURI
|
||||
case errors.Is(err, oauth2server.ErrUnauthorizedMember):
|
||||
return oauth2server.NewError(oauth2server.ErrUnauthorizedClient, oauth2server.WithDescription("client is private and user is not a member of the organization"))
|
||||
case errors.Is(err, oauth2server.ErrDeviceCodeNotPending):
|
||||
return oauth2server.NewError(oauth2server.ErrInvalidGrant, oauth2server.WithDescription("device code is not pending"))
|
||||
case errors.Is(err, oauth2.ErrClientNotFound):
|
||||
return oauth2.NewError(oauth2.ErrInvalidClient, oauth2.WithDescription("client not found"))
|
||||
case errors.Is(err, oauth2.ErrInvalidRedirectURI):
|
||||
return oauth2.ErrInvalidRedirectURI
|
||||
case errors.Is(err, oauth2.ErrUnauthorizedMember):
|
||||
return oauth2.NewError(oauth2.ErrUnauthorizedClient, oauth2.WithDescription("client is private and user is not a member of the organization"))
|
||||
case errors.Is(err, oauth2.ErrDeviceCodeNotPending):
|
||||
return oauth2.NewError(oauth2.ErrInvalidGrant, oauth2.WithDescription("device code is not pending"))
|
||||
default:
|
||||
if oauthErr, ok := errors.AsType[*oauth2server.OAuth2Error](err); ok {
|
||||
if oauthErr, ok := errors.AsType[*oauth2.OAuth2Error](err); ok {
|
||||
return oauthErr
|
||||
}
|
||||
|
||||
return oauth2server.NewError(oauth2server.ErrServerError, oauth2server.WithDescription("internal error"))
|
||||
return oauth2.NewError(oauth2.ErrServerError, oauth2.WithDescription("internal error"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ func redirectWithError(w http.ResponseWriter, r *http.Request, redirectURI, stat
|
||||
return
|
||||
}
|
||||
|
||||
oauthErr, ok := errors.AsType[*oauth2server.OAuth2Error](err)
|
||||
oauthErr, ok := errors.AsType[*oauth2.OAuth2Error](err)
|
||||
if !ok {
|
||||
httpserver.RenderError(w, http.StatusInternalServerError, errors.New("internal server error"))
|
||||
return
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package connect_v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -30,18 +29,13 @@ import (
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/iam"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2server"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2"
|
||||
"go.probo.inc/probo/pkg/securecookie"
|
||||
"go.probo.inc/probo/pkg/server/api/authn"
|
||||
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
|
||||
"go.probo.inc/probo/pkg/uri"
|
||||
)
|
||||
|
||||
var (
|
||||
oauth2ClientContextKey = &ctxKey{name: "oauth2_client"}
|
||||
oauth2AccessTokenContextKey = &ctxKey{name: "oauth2_access_token"}
|
||||
)
|
||||
|
||||
type OAuth2Handler struct {
|
||||
iam *iam.Service
|
||||
sessionCookie *authn.Cookie
|
||||
@@ -63,29 +57,17 @@ func NewOAuth2Handler(
|
||||
}
|
||||
}
|
||||
|
||||
// oauth2ClientFromContext returns the authenticated OAuth2 client from context.
|
||||
func oauth2ClientFromContext(r *http.Request) *coredata.OAuth2Client {
|
||||
client, _ := r.Context().Value(oauth2ClientContextKey).(*coredata.OAuth2Client)
|
||||
return client
|
||||
}
|
||||
|
||||
// oauth2AccessTokenFromContext returns the validated OAuth2 access token from context.
|
||||
func oauth2AccessTokenFromContext(r *http.Request) *coredata.OAuth2AccessToken {
|
||||
token, _ := r.Context().Value(oauth2AccessTokenContextKey).(*coredata.OAuth2AccessToken)
|
||||
return token
|
||||
}
|
||||
|
||||
// ClientAuthMiddleware authenticates the OAuth2 client from HTTP Basic auth
|
||||
// or POST body credentials and stores it in the request context.
|
||||
func (h *OAuth2Handler) ClientAuthMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
client, err := h.authenticateClient(r)
|
||||
if err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.ErrInvalidClient)
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.ErrInvalidClient)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), oauth2ClientContextKey, client)
|
||||
ctx := oauth2.ContextWithClient(r.Context(), client)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
@@ -110,15 +92,15 @@ func (h *OAuth2Handler) BearerTokenMiddleware(next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), oauth2AccessTokenContextKey, accessToken)
|
||||
ctx := oauth2.ContextWithAccessToken(r.Context(), accessToken)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
func (h *OAuth2Handler) endpoints() oauth2server.Endpoints {
|
||||
func (h *OAuth2Handler) endpoints() oauth2.Endpoints {
|
||||
api := h.baseURL.String() + "/api/connect/v1"
|
||||
|
||||
return oauth2server.Endpoints{
|
||||
return oauth2.Endpoints{
|
||||
Authorization: uri.URI(api + "/oauth2/authorize"),
|
||||
Token: uri.URI(api + "/oauth2/token"),
|
||||
Userinfo: uri.URI(api + "/oauth2/userinfo"),
|
||||
@@ -135,7 +117,7 @@ func (h *OAuth2Handler) endpoints() oauth2server.Endpoints {
|
||||
// DiscoveryHandler serves the OpenID Connect Discovery document.
|
||||
// GET /.well-known/openid-configuration
|
||||
func (h *OAuth2Handler) DiscoveryHandler(w http.ResponseWriter, r *http.Request) {
|
||||
metadata := h.iam.OAuth2ServerService.Metadata(h.endpoints())
|
||||
metadata := h.iam.OAuth2ServerMetadata(h.endpoints())
|
||||
|
||||
PublicCache(w, 1*time.Hour)
|
||||
httpserver.RenderJSON(w, http.StatusOK, metadata)
|
||||
@@ -168,7 +150,7 @@ func (h *OAuth2Handler) AuthorizeHandler(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
var in types.OAuth2AuthorizeInput
|
||||
if err := in.DecodeQuery(r.URL.Query()); err != nil {
|
||||
h.handleAuthorizeError(w, r, oauth2server.NewError(oauth2server.ErrInvalidRequest, oauth2server.WithError(err)), "", "")
|
||||
h.handleAuthorizeError(w, r, oauth2.NewError(oauth2.ErrInvalidRequest, oauth2.WithError(err)), "", "")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -181,7 +163,7 @@ func (h *OAuth2Handler) AuthorizeHandler(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
code, err := h.iam.OAuth2ServerService.Authorize(
|
||||
r.Context(),
|
||||
&oauth2server.AuthorizeRequest{
|
||||
&oauth2.AuthorizeRequest{
|
||||
IdentityID: identity.ID,
|
||||
SessionID: session.ID,
|
||||
ResponseType: in.ResponseType,
|
||||
@@ -196,7 +178,7 @@ func (h *OAuth2Handler) AuthorizeHandler(w http.ResponseWriter, r *http.Request)
|
||||
},
|
||||
)
|
||||
|
||||
if consentErr, ok := errors.AsType[*oauth2server.ConsentRequiredError](err); ok {
|
||||
if consentErr, ok := errors.AsType[*oauth2.ConsentRequiredError](err); ok {
|
||||
consentURL := h.baseURL.WithPath("/auth/consent").
|
||||
WithQuery("consent_id", consentErr.ConsentID.String()).
|
||||
MustString()
|
||||
@@ -217,7 +199,7 @@ func (h *OAuth2Handler) AuthorizeHandler(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
func (h *OAuth2Handler) TokenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidRequest, oauth2server.WithDescription("invalid form data")))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidRequest, oauth2.WithDescription("invalid form data")))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -227,7 +209,7 @@ func (h *OAuth2Handler) TokenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
)
|
||||
|
||||
if err := grantType.UnmarshalText([]byte(value)); err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.ErrUnsupportedGrantType)
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.ErrUnsupportedGrantType)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -244,13 +226,15 @@ func (h *OAuth2Handler) TokenHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (h *OAuth2Handler) IntrospectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
client = oauth2ClientFromContext(r)
|
||||
in = types.OAuth2IntrospectInput{}
|
||||
)
|
||||
client, ok := oauth2.ClientFromContext(r.Context())
|
||||
if !ok {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.ErrInvalidClient)
|
||||
return
|
||||
}
|
||||
|
||||
in := types.OAuth2IntrospectInput{}
|
||||
if err := in.DecodeForm(r); err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidRequest, oauth2server.WithError(err)))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidRequest, oauth2.WithError(err)))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -270,12 +254,12 @@ func (h *OAuth2Handler) IntrospectHandler(w http.ResponseWriter, r *http.Request
|
||||
|
||||
func (h *OAuth2Handler) RevokeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
client = oauth2ClientFromContext(r)
|
||||
in = types.OAuth2RevokeInput{}
|
||||
client, _ = oauth2.ClientFromContext(r.Context())
|
||||
in = types.OAuth2RevokeInput{}
|
||||
)
|
||||
|
||||
if err := in.DecodeForm(r); err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidRequest, oauth2server.WithError(err)))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidRequest, oauth2.WithError(err)))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -300,7 +284,7 @@ func (h *OAuth2Handler) RevokeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
func (h *OAuth2Handler) DeviceAuthHandler(w http.ResponseWriter, r *http.Request) {
|
||||
in := types.OAuth2DeviceAuthInput{}
|
||||
if err := in.DecodeForm(r); err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidRequest, oauth2server.WithError(err)))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidRequest, oauth2.WithError(err)))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -345,7 +329,7 @@ func (h *OAuth2Handler) RegisterHandler(w http.ResponseWriter, r *http.Request)
|
||||
h.renderOAuth2ErrorResponse(
|
||||
w,
|
||||
r,
|
||||
oauth2server.NewError(oauth2server.ErrInvalidRequest, oauth2server.WithDescription("invalid JSON body")),
|
||||
oauth2.NewError(oauth2.ErrInvalidRequest, oauth2.WithDescription("invalid JSON body")),
|
||||
)
|
||||
|
||||
return
|
||||
@@ -369,15 +353,15 @@ func (h *OAuth2Handler) RegisterHandler(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
if len(in.Scopes) == 0 {
|
||||
in.Scopes = coredata.OAuth2Scopes{
|
||||
coredata.OAuth2ScopeOpenID,
|
||||
coredata.OAuth2ScopeProfile,
|
||||
coredata.OAuth2ScopeEmail,
|
||||
oauth2.ScopeOpenID,
|
||||
oauth2.ScopeProfile,
|
||||
oauth2.ScopeEmail,
|
||||
}
|
||||
}
|
||||
|
||||
clientID, clientSecret, err := h.iam.OAuth2ServerService.RegisterClient(
|
||||
r.Context(),
|
||||
&oauth2server.RegisterClientRequest{
|
||||
&oauth2.RegisterClientRequest{
|
||||
IdentityID: identity.ID,
|
||||
OrganizationID: in.OrganizationID,
|
||||
ClientName: in.ClientName,
|
||||
@@ -417,7 +401,13 @@ func (h *OAuth2Handler) RegisterHandler(w http.ResponseWriter, r *http.Request)
|
||||
// UserInfoHandler serves the OIDC UserInfo endpoint.
|
||||
// GET /oauth2/userinfo
|
||||
func (h *OAuth2Handler) UserInfoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
accessToken := oauth2AccessTokenFromContext(r)
|
||||
accessToken, ok := oauth2.AccessTokenFromContext(r.Context())
|
||||
if !ok {
|
||||
w.Header().Set("WWW-Authenticate", `Bearer error="invalid_token"`)
|
||||
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := h.iam.OAuth2ServerService.UserInfo(
|
||||
r.Context(),
|
||||
@@ -425,7 +415,7 @@ func (h *OAuth2Handler) UserInfoHandler(w http.ResponseWriter, r *http.Request)
|
||||
accessToken.Scopes,
|
||||
)
|
||||
if err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.ErrServerError)
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.ErrServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -452,12 +442,12 @@ func (h *OAuth2Handler) authenticateClient(r *http.Request) (*coredata.OAuth2Cli
|
||||
}
|
||||
|
||||
if clientIDStr == "" {
|
||||
return nil, oauth2server.ErrInvalidClient
|
||||
return nil, oauth2.ErrInvalidClient
|
||||
}
|
||||
|
||||
clientID, err := gid.ParseGID(clientIDStr)
|
||||
if err != nil {
|
||||
return nil, oauth2server.ErrInvalidClient
|
||||
return nil, oauth2.ErrInvalidClient
|
||||
}
|
||||
|
||||
return h.iam.OAuth2ServerService.AuthenticateClient(r.Context(), clientID, clientSecret)
|
||||
@@ -466,13 +456,13 @@ func (h *OAuth2Handler) authenticateClient(r *http.Request) (*coredata.OAuth2Cli
|
||||
func (h *OAuth2Handler) handleAuthorizationCodeGrant(w http.ResponseWriter, r *http.Request) {
|
||||
client, err := h.authenticateClient(r)
|
||||
if err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.ErrInvalidClient)
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.ErrInvalidClient)
|
||||
return
|
||||
}
|
||||
|
||||
var in types.OAuth2AuthorizationCodeGrantInput
|
||||
if err := in.DecodeForm(r); err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidGrant, oauth2server.WithError(err)))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidGrant, oauth2.WithError(err)))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -484,7 +474,7 @@ func (h *OAuth2Handler) handleAuthorizationCodeGrant(w http.ResponseWriter, r *h
|
||||
in.CodeVerifier,
|
||||
)
|
||||
if err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidGrant, oauth2server.WithDescription("invalid or expired code")))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidGrant, oauth2.WithDescription("invalid or expired code")))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -495,19 +485,19 @@ func (h *OAuth2Handler) handleAuthorizationCodeGrant(w http.ResponseWriter, r *h
|
||||
func (h *OAuth2Handler) handleRefreshTokenGrant(w http.ResponseWriter, r *http.Request) {
|
||||
client, err := h.authenticateClient(r)
|
||||
if err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.ErrInvalidClient)
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.ErrInvalidClient)
|
||||
return
|
||||
}
|
||||
|
||||
var in types.OAuth2RefreshTokenGrantInput
|
||||
if err := in.DecodeForm(r); err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidGrant, oauth2server.WithError(err)))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidGrant, oauth2.WithError(err)))
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.iam.OAuth2ServerService.RefreshToken(r.Context(), client, in.RefreshToken)
|
||||
if err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidGrant, oauth2server.WithDescription("invalid or expired refresh token")))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidGrant, oauth2.WithDescription("invalid or expired refresh token")))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -518,7 +508,7 @@ func (h *OAuth2Handler) handleRefreshTokenGrant(w http.ResponseWriter, r *http.R
|
||||
func (h *OAuth2Handler) handleDeviceCodeGrant(w http.ResponseWriter, r *http.Request) {
|
||||
var in types.OAuth2DeviceCodeGrantInput
|
||||
if err := in.DecodeForm(r); err != nil {
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2server.NewError(oauth2server.ErrInvalidRequest, oauth2server.WithError(err)))
|
||||
h.renderOAuth2ErrorResponse(w, r, oauth2.NewError(oauth2.ErrInvalidRequest, oauth2.WithError(err)))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -536,7 +526,7 @@ func (h *OAuth2Handler) handleDeviceCodeGrant(w http.ResponseWriter, r *http.Req
|
||||
httpserver.RenderJSON(w, http.StatusOK, tokenResultToResponse(result))
|
||||
}
|
||||
|
||||
func tokenResultToResponse(r *oauth2server.TokenResult) *types.OAuth2TokenResponse {
|
||||
func tokenResultToResponse(r *oauth2.TokenResult) *types.OAuth2TokenResponse {
|
||||
return &types.OAuth2TokenResponse{
|
||||
AccessToken: r.AccessToken,
|
||||
TokenType: r.TokenType,
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"go.gearno.de/kit/log"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2server"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2"
|
||||
"go.probo.inc/probo/pkg/server/api/authn"
|
||||
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
|
||||
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
|
||||
@@ -39,13 +39,13 @@ func (r *mutationResolver) AuthorizeDevice(ctx context.Context, input types.Auth
|
||||
|
||||
err := r.iam.OAuth2ServerService.AuthorizeDevice(ctx, identity.ID, session.ID, userCode)
|
||||
if err != nil {
|
||||
if consentErr, ok := errors.AsType[*oauth2server.ConsentRequiredError](err); ok {
|
||||
if consentErr, ok := errors.AsType[*oauth2.ConsentRequiredError](err); ok {
|
||||
return &types.AuthorizeDevicePayload{
|
||||
ConsentID: &consentErr.ConsentID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if oauthErr, ok := errors.AsType[*oauth2server.OAuth2Error](err); ok {
|
||||
if oauthErr, ok := errors.AsType[*oauth2.OAuth2Error](err); ok {
|
||||
return nil, gqlutils.Invalidf(ctx, "%s", oauthErr.Description())
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ func (r *mutationResolver) ApproveConsent(ctx context.Context, input types.Appro
|
||||
|
||||
result, err := r.iam.OAuth2ServerService.ApproveConsent(
|
||||
ctx,
|
||||
&oauth2server.ConsentApprovalRequest{
|
||||
&oauth2.ConsentApprovalRequest{
|
||||
ConsentID: input.ConsentID,
|
||||
IdentityID: identity.ID,
|
||||
SessionID: session.ID,
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2server"
|
||||
"go.probo.inc/probo/pkg/iam/oauth2"
|
||||
"go.probo.inc/probo/pkg/uri"
|
||||
)
|
||||
|
||||
@@ -328,7 +328,7 @@ func InactiveIntrospectResponse() *OAuth2IntrospectResponse {
|
||||
return &OAuth2IntrospectResponse{Active: false}
|
||||
}
|
||||
|
||||
func ActiveIntrospectResponse(result *oauth2server.IntrospectResult) *OAuth2IntrospectResponse {
|
||||
func ActiveIntrospectResponse(result *oauth2.IntrospectResult) *OAuth2IntrospectResponse {
|
||||
return &OAuth2IntrospectResponse{
|
||||
Active: true,
|
||||
Scope: result.Scopes,
|
||||
|
||||
Reference in New Issue
Block a user