intermediate commit with some methods implemented
This commit is contained in:
parent
4fcda01738
commit
2902a81161
6 changed files with 214 additions and 46 deletions
|
@ -63,41 +63,51 @@ func DeviceAuthorizationHandler(o OpenIDProvider) func(http.ResponseWriter, *htt
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeviceAuthorization(w http.ResponseWriter, r *http.Request, o OpenIDProvider) error {
|
func DeviceAuthorization(w http.ResponseWriter, r *http.Request, o OpenIDProvider) error {
|
||||||
storage, err := assertDeviceStorage(o.Storage())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := ParseDeviceCodeRequest(r, o)
|
req, err := ParseDeviceCodeRequest(r, o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
response, err := createDeviceAuthorization(r.Context(), req, req.ClientID, o)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
httphelper.MarshalJSON(w, response)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDeviceAuthorization(ctx context.Context, req *oidc.DeviceAuthorizationRequest, clientID string, o OpenIDProvider) (*oidc.DeviceAuthorizationResponse, error) {
|
||||||
|
storage, err := assertDeviceStorage(o.Storage())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
config := o.DeviceAuthorization()
|
config := o.DeviceAuthorization()
|
||||||
|
|
||||||
deviceCode, err := NewDeviceCode(RecommendedDeviceCodeBytes)
|
deviceCode, err := NewDeviceCode(RecommendedDeviceCodeBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, NewStatusError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
userCode, err := NewUserCode([]rune(config.UserCode.CharSet), config.UserCode.CharAmount, config.UserCode.DashInterval)
|
userCode, err := NewUserCode([]rune(config.UserCode.CharSet), config.UserCode.CharAmount, config.UserCode.DashInterval)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, NewStatusError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
expires := time.Now().Add(config.Lifetime)
|
expires := time.Now().Add(config.Lifetime)
|
||||||
err = storage.StoreDeviceAuthorization(r.Context(), req.ClientID, deviceCode, userCode, expires, req.Scopes)
|
err = storage.StoreDeviceAuthorization(ctx, clientID, deviceCode, userCode, expires, req.Scopes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, NewStatusError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
var verification *url.URL
|
var verification *url.URL
|
||||||
if config.UserFormURL != "" {
|
if config.UserFormURL != "" {
|
||||||
if verification, err = url.Parse(config.UserFormURL); err != nil {
|
if verification, err = url.Parse(config.UserFormURL); err != nil {
|
||||||
return oidc.ErrServerError().WithParent(err).WithDescription("invalid URL for device user form")
|
err = oidc.ErrServerError().WithParent(err).WithDescription("invalid URL for device user form")
|
||||||
|
return nil, NewStatusError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if verification, err = url.Parse(IssuerFromContext(r.Context())); err != nil {
|
if verification, err = url.Parse(IssuerFromContext(ctx)); err != nil {
|
||||||
return oidc.ErrServerError().WithParent(err).WithDescription("invalid URL for issuer")
|
err = oidc.ErrServerError().WithParent(err).WithDescription("invalid URL for issuer")
|
||||||
|
return nil, NewStatusError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
verification.Path = config.UserFormPath
|
verification.Path = config.UserFormPath
|
||||||
}
|
}
|
||||||
|
@ -112,9 +122,7 @@ func DeviceAuthorization(w http.ResponseWriter, r *http.Request, o OpenIDProvide
|
||||||
|
|
||||||
verification.RawQuery = "user_code=" + userCode
|
verification.RawQuery = "user_code=" + userCode
|
||||||
response.VerificationURIComplete = verification.String()
|
response.VerificationURIComplete = verification.String()
|
||||||
|
return response, nil
|
||||||
httphelper.MarshalJSON(w, response)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseDeviceCodeRequest(r *http.Request, o OpenIDProvider) (*oidc.DeviceAuthorizationRequest, error) {
|
func ParseDeviceCodeRequest(r *http.Request, o OpenIDProvider) (*oidc.DeviceAuthorizationRequest, error) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ var DefaultSupportedScopes = []string{
|
||||||
|
|
||||||
func discoveryHandler(c Configuration, s DiscoverStorage) func(http.ResponseWriter, *http.Request) {
|
func discoveryHandler(c Configuration, s DiscoverStorage) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
Discover(w, CreateDiscoveryConfig(r, c, s))
|
Discover(w, CreateDiscoveryConfig(r.Context(), c, s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ func Discover(w http.ResponseWriter, config *oidc.DiscoveryConfiguration) {
|
||||||
httphelper.MarshalJSON(w, config)
|
httphelper.MarshalJSON(w, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateDiscoveryConfig(r *http.Request, config Configuration, storage DiscoverStorage) *oidc.DiscoveryConfiguration {
|
func CreateDiscoveryConfig(ctx context.Context, config Configuration, storage DiscoverStorage) *oidc.DiscoveryConfiguration {
|
||||||
issuer := config.IssuerFromRequest(r)
|
issuer := IssuerFromContext(ctx)
|
||||||
return &oidc.DiscoveryConfiguration{
|
return &oidc.DiscoveryConfiguration{
|
||||||
Issuer: issuer,
|
Issuer: issuer,
|
||||||
AuthorizationEndpoint: config.AuthorizationEndpoint().Absolute(issuer),
|
AuthorizationEndpoint: config.AuthorizationEndpoint().Absolute(issuer),
|
||||||
|
@ -49,7 +49,7 @@ func CreateDiscoveryConfig(r *http.Request, config Configuration, storage Discov
|
||||||
ResponseTypesSupported: ResponseTypes(config),
|
ResponseTypesSupported: ResponseTypes(config),
|
||||||
GrantTypesSupported: GrantTypes(config),
|
GrantTypesSupported: GrantTypes(config),
|
||||||
SubjectTypesSupported: SubjectTypes(config),
|
SubjectTypesSupported: SubjectTypes(config),
|
||||||
IDTokenSigningAlgValuesSupported: SigAlgorithms(r.Context(), storage),
|
IDTokenSigningAlgValuesSupported: SigAlgorithms(ctx, storage),
|
||||||
RequestObjectSigningAlgValuesSupported: RequestObjectSigAlgorithms(config),
|
RequestObjectSigningAlgValuesSupported: RequestObjectSigAlgorithms(config),
|
||||||
TokenEndpointAuthMethodsSupported: AuthMethodsTokenEndpoint(config),
|
TokenEndpointAuthMethodsSupported: AuthMethodsTokenEndpoint(config),
|
||||||
TokenEndpointAuthSigningAlgValuesSupported: TokenSigAlgorithms(config),
|
TokenEndpointAuthSigningAlgValuesSupported: TokenSigAlgorithms(config),
|
||||||
|
|
|
@ -48,9 +48,9 @@ func TestDiscover(t *testing.T) {
|
||||||
|
|
||||||
func TestCreateDiscoveryConfig(t *testing.T) {
|
func TestCreateDiscoveryConfig(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
request *http.Request
|
ctx context.Context
|
||||||
c op.Configuration
|
c op.Configuration
|
||||||
s op.DiscoverStorage
|
s op.DiscoverStorage
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -61,7 +61,7 @@ func TestCreateDiscoveryConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
got := op.CreateDiscoveryConfig(tt.args.request, tt.args.c, tt.args.s)
|
got := op.CreateDiscoveryConfig(tt.args.ctx, tt.args.c, tt.args.s)
|
||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package op
|
package op
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
httphelper "github.com/zitadel/oidc/v3/pkg/http"
|
httphelper "github.com/zitadel/oidc/v3/pkg/http"
|
||||||
|
@ -66,3 +67,34 @@ func RequestError(w http.ResponseWriter, r *http.Request, err error, logger *slo
|
||||||
logger.Log(r.Context(), e.LogLevel(), "request error", "oidc_error", e)
|
logger.Log(r.Context(), e.LogLevel(), "request error", "oidc_error", e)
|
||||||
httphelper.MarshalJSONWithStatus(w, e, status)
|
httphelper.MarshalJSONWithStatus(w, e, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TryErrorRedirect(ctx context.Context, authReq ErrAuthRequest, parent error, encoder httphelper.Encoder, logger *slog.Logger) (*Redirect, error) {
|
||||||
|
e := oidc.DefaultToServerError(parent, parent.Error())
|
||||||
|
logger = logger.With("oidc_error", e)
|
||||||
|
|
||||||
|
if authReq == nil {
|
||||||
|
logger.Log(ctx, e.LogLevel(), "auth request")
|
||||||
|
return nil, NewStatusError(parent, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if logAuthReq, ok := authReq.(LogAuthRequest); ok {
|
||||||
|
logger = logger.With("auth_request", logAuthReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
if authReq.GetRedirectURI() == "" || e.IsRedirectDisabled() {
|
||||||
|
logger.Log(ctx, e.LogLevel(), "auth request: not redirecting")
|
||||||
|
return nil, NewStatusError(parent, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.State = authReq.GetState()
|
||||||
|
var responseMode oidc.ResponseMode
|
||||||
|
if rm, ok := authReq.(interface{ GetResponseMode() oidc.ResponseMode }); ok {
|
||||||
|
responseMode = rm.GetResponseMode()
|
||||||
|
}
|
||||||
|
url, err := AuthResponseURL(authReq.GetRedirectURI(), authReq.GetResponseType(), responseMode, e, encoder)
|
||||||
|
if err != nil {
|
||||||
|
logger.ErrorContext(ctx, "auth response URL", "error", err)
|
||||||
|
return nil, NewStatusError(err, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
return NewRedirect(url), nil
|
||||||
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ type Server interface {
|
||||||
// DeviceAuthorization initiates the device authorization flow.
|
// DeviceAuthorization initiates the device authorization flow.
|
||||||
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.1
|
// https://datatracker.ietf.org/doc/html/rfc8628#section-3.1
|
||||||
// The recommended Response Data type is [oidc.DeviceAuthorizationResponse].
|
// The recommended Response Data type is [oidc.DeviceAuthorizationResponse].
|
||||||
DeviceAuthorization(context.Context, *Request[oidc.DeviceAuthorizationRequest]) (*Response, error)
|
DeviceAuthorization(context.Context, *ClientRequest[oidc.DeviceAuthorizationRequest]) (*Response, error)
|
||||||
|
|
||||||
// VerifyClient is called on most oauth/token handlers to authenticate,
|
// VerifyClient is called on most oauth/token handlers to authenticate,
|
||||||
// using either a secret (POST, Basic) or assertion (JWT).
|
// using either a secret (POST, Basic) or assertion (JWT).
|
||||||
|
@ -137,7 +137,7 @@ type Server interface {
|
||||||
// Introspect handles the OAuth 2.0 Token Introspection endpoint.
|
// Introspect handles the OAuth 2.0 Token Introspection endpoint.
|
||||||
// https://datatracker.ietf.org/doc/html/rfc7662
|
// https://datatracker.ietf.org/doc/html/rfc7662
|
||||||
// The recommended Response Data type is [oidc.IntrospectionResponse].
|
// The recommended Response Data type is [oidc.IntrospectionResponse].
|
||||||
Introspect(context.Context, *Request[oidc.IntrospectionRequest]) (*Response, error)
|
Introspect(context.Context, *ClientRequest[oidc.IntrospectionRequest]) (*Response, error)
|
||||||
|
|
||||||
// UserInfo handles the UserInfo endpoint and returns Claims about the authenticated End-User.
|
// UserInfo handles the UserInfo endpoint and returns Claims about the authenticated End-User.
|
||||||
// https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
|
// https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
|
||||||
|
@ -231,19 +231,18 @@ func (resp *Response) writeOut(w http.ResponseWriter) {
|
||||||
|
|
||||||
// Redirect is a special response type which will
|
// Redirect is a special response type which will
|
||||||
// initiate a [http.StatusFound] redirect.
|
// initiate a [http.StatusFound] redirect.
|
||||||
// The Params field will be encoded and set to the
|
// The Params fielde will be encoded and set to the
|
||||||
// URL's RawQuery field before building the URL.
|
// URL's RawQuery field before building the URL.
|
||||||
//
|
|
||||||
// If the RawQuery contains values that need to persist,
|
|
||||||
// the implementation should parse them into Params and
|
|
||||||
// add request specific values after.
|
|
||||||
type Redirect struct {
|
type Redirect struct {
|
||||||
// Header map will be merged with the
|
// Header map will be merged with the
|
||||||
// header on the [http.ResponseWriter].
|
// header on the [http.ResponseWriter].
|
||||||
Header http.Header
|
Header http.Header
|
||||||
|
|
||||||
URL url.URL
|
URL string
|
||||||
Params url.Values
|
}
|
||||||
|
|
||||||
|
func NewRedirect(url string) *Redirect {
|
||||||
|
return &Redirect{URL: url}
|
||||||
}
|
}
|
||||||
|
|
||||||
type UnimplementedServer struct{}
|
type UnimplementedServer struct{}
|
||||||
|
@ -280,8 +279,8 @@ func (UnimplementedServer) Authorize(_ context.Context, r *Request[oidc.AuthRequ
|
||||||
return nil, unimplementedError(r)
|
return nil, unimplementedError(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UnimplementedServer) DeviceAuthorization(_ context.Context, r *Request[oidc.DeviceAuthorizationRequest]) (*Response, error) {
|
func (UnimplementedServer) DeviceAuthorization(_ context.Context, r *ClientRequest[oidc.DeviceAuthorizationRequest]) (*Response, error) {
|
||||||
return nil, unimplementedError(r)
|
return nil, unimplementedError(r.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UnimplementedServer) VerifyClient(_ context.Context, r *Request[ClientCredentials]) (Client, error) {
|
func (UnimplementedServer) VerifyClient(_ context.Context, r *Request[ClientCredentials]) (Client, error) {
|
||||||
|
@ -312,8 +311,8 @@ func (UnimplementedServer) DeviceToken(_ context.Context, r *ClientRequest[oidc.
|
||||||
return nil, unimplementedError(r.Request)
|
return nil, unimplementedError(r.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UnimplementedServer) Introspect(_ context.Context, r *Request[oidc.IntrospectionRequest]) (*Response, error) {
|
func (UnimplementedServer) Introspect(_ context.Context, r *ClientRequest[oidc.IntrospectionRequest]) (*Response, error) {
|
||||||
return nil, unimplementedError(r)
|
return nil, unimplementedError(r.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UnimplementedServer) UserInfo(_ context.Context, r *Request[oidc.UserInfoRequest]) (*Response, error) {
|
func (UnimplementedServer) UserInfo(_ context.Context, r *Request[oidc.UserInfoRequest]) (*Response, error) {
|
||||||
|
|
|
@ -2,23 +2,97 @@ package op
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/zitadel/oidc/v3/pkg/oidc"
|
"github.com/zitadel/oidc/v3/pkg/oidc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LegacyServer struct {
|
type LegacyServer struct {
|
||||||
UnimplementedServer
|
UnimplementedServer
|
||||||
op *Provider
|
provider OpenIDProvider
|
||||||
|
|
||||||
|
readyProbes []ProbesFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) Health(_ context.Context, r *Request[struct{}]) (*Response, error) {
|
||||||
|
return NewResponse(Status{Status: "ok"}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) Ready(ctx context.Context, r *Request[struct{}]) (*Response, error) {
|
||||||
|
for _, probe := range s.readyProbes {
|
||||||
|
// shouldn't we run probes in Go routines?
|
||||||
|
if err := probe(ctx); err != nil {
|
||||||
|
return nil, NewStatusError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NewResponse(Status{Status: "ok"}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) Discovery(ctx context.Context, r *Request[struct{}]) (*Response, error) {
|
||||||
|
return NewResponse(
|
||||||
|
CreateDiscoveryConfig(ctx, s.provider, s.provider.Storage()),
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrAuthReqMissingClientID = errors.New("auth request is missing client_id")
|
||||||
|
ErrAuthReqMissingRedirectURI = errors.New("auth request is missing redirect_uri")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *LegacyServer) Authorize(ctx context.Context, r *Request[oidc.AuthRequest]) (_ *Redirect, err error) {
|
||||||
|
authReq := r.Data
|
||||||
|
if authReq.RequestParam != "" && s.provider.RequestObjectSupported() {
|
||||||
|
authReq, err = ParseRequestObject(ctx, authReq, s.provider.Storage(), IssuerFromContext(ctx))
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewStatusError(err, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if authReq.ClientID == "" {
|
||||||
|
return TryErrorRedirect(ctx, authReq, ErrAuthReqMissingClientID, s.provider.Encoder(), s.provider.Logger())
|
||||||
|
}
|
||||||
|
if authReq.RedirectURI == "" {
|
||||||
|
return TryErrorRedirect(ctx, authReq, ErrAuthReqMissingRedirectURI, s.provider.Encoder(), s.provider.Logger())
|
||||||
|
}
|
||||||
|
validation := ValidateAuthRequest
|
||||||
|
if validater, ok := s.provider.(AuthorizeValidator); ok {
|
||||||
|
validation = validater.ValidateAuthRequest
|
||||||
|
}
|
||||||
|
userID, err := validation(ctx, authReq, s.provider.Storage(), s.provider.IDTokenHintVerifier(ctx))
|
||||||
|
if err != nil {
|
||||||
|
return TryErrorRedirect(ctx, authReq, err, s.provider.Encoder(), s.provider.Logger())
|
||||||
|
}
|
||||||
|
if authReq.RequestParam != "" {
|
||||||
|
return TryErrorRedirect(ctx, authReq, oidc.ErrRequestNotSupported(), s.provider.Encoder(), s.provider.Logger())
|
||||||
|
}
|
||||||
|
req, err := s.provider.Storage().CreateAuthRequest(ctx, authReq, userID)
|
||||||
|
if err != nil {
|
||||||
|
return TryErrorRedirect(ctx, authReq, oidc.DefaultToServerError(err, "unable to save auth request"), s.provider.Encoder(), s.provider.Logger())
|
||||||
|
}
|
||||||
|
client, err := s.provider.Storage().GetClientByClientID(ctx, req.GetClientID())
|
||||||
|
if err != nil {
|
||||||
|
return TryErrorRedirect(ctx, authReq, oidc.DefaultToServerError(err, "unable to retrieve client by id"), s.provider.Encoder(), s.provider.Logger())
|
||||||
|
}
|
||||||
|
return NewRedirect(client.LoginURL(req.GetID())), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) DeviceAuthorization(ctx context.Context, r *ClientRequest[oidc.DeviceAuthorizationRequest]) (*Response, error) {
|
||||||
|
response, err := createDeviceAuthorization(ctx, r.Data, r.Client.GetID(), s.provider)
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewStatusError(err, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
return NewResponse(response), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LegacyServer) VerifyClient(ctx context.Context, r *Request[ClientCredentials]) (Client, error) {
|
func (s *LegacyServer) VerifyClient(ctx context.Context, r *Request[ClientCredentials]) (Client, error) {
|
||||||
if r.Data.ClientAssertionType == oidc.ClientAssertionTypeJWTAssertion {
|
if r.Data.ClientAssertionType == oidc.ClientAssertionTypeJWTAssertion {
|
||||||
if !s.op.AuthMethodPrivateKeyJWTSupported() {
|
jwtExchanger, ok := s.provider.(JWTAuthorizationGrantExchanger)
|
||||||
|
if !ok || !s.provider.AuthMethodPrivateKeyJWTSupported() {
|
||||||
return nil, oidc.ErrInvalidClient().WithDescription("auth_method private_key_jwt not supported")
|
return nil, oidc.ErrInvalidClient().WithDescription("auth_method private_key_jwt not supported")
|
||||||
}
|
}
|
||||||
return AuthorizePrivateJWTKey(ctx, r.Data.ClientAssertion, s.op)
|
return AuthorizePrivateJWTKey(ctx, r.Data.ClientAssertion, jwtExchanger)
|
||||||
}
|
}
|
||||||
client, err := s.op.Storage().GetClientByClientID(ctx, r.Data.ClientID)
|
client, err := s.provider.Storage().GetClientByClientID(ctx, r.Data.ClientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, oidc.ErrInvalidClient().WithParent(err)
|
return nil, oidc.ErrInvalidClient().WithParent(err)
|
||||||
}
|
}
|
||||||
|
@ -29,12 +103,12 @@ func (s *LegacyServer) VerifyClient(ctx context.Context, r *Request[ClientCreden
|
||||||
case oidc.AuthMethodPrivateKeyJWT:
|
case oidc.AuthMethodPrivateKeyJWT:
|
||||||
return nil, oidc.ErrInvalidClient().WithDescription("private_key_jwt not allowed for this client")
|
return nil, oidc.ErrInvalidClient().WithDescription("private_key_jwt not allowed for this client")
|
||||||
case oidc.AuthMethodPost:
|
case oidc.AuthMethodPost:
|
||||||
if !s.op.AuthMethodPostSupported() {
|
if !s.provider.AuthMethodPostSupported() {
|
||||||
return nil, oidc.ErrInvalidClient().WithDescription("auth_method post not supported")
|
return nil, oidc.ErrInvalidClient().WithDescription("auth_method post not supported")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = AuthorizeClientIDSecret(ctx, r.Data.ClientID, r.Data.ClientSecret, s.op.storage)
|
err = AuthorizeClientIDSecret(ctx, r.Data.ClientID, r.Data.ClientSecret, s.provider.Storage())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -43,7 +117,7 @@ func (s *LegacyServer) VerifyClient(ctx context.Context, r *Request[ClientCreden
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LegacyServer) CodeExchange(ctx context.Context, r *ClientRequest[oidc.AccessTokenRequest]) (*Response, error) {
|
func (s *LegacyServer) CodeExchange(ctx context.Context, r *ClientRequest[oidc.AccessTokenRequest]) (*Response, error) {
|
||||||
authReq, err := AuthRequestByCode(ctx, s.op.storage, r.Data.Code)
|
authReq, err := AuthRequestByCode(ctx, s.provider.Storage(), r.Data.Code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -52,7 +126,7 @@ func (s *LegacyServer) CodeExchange(ctx context.Context, r *ClientRequest[oidc.A
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp, err := CreateTokenResponse(ctx, authReq, r.Client, s.op, true, r.Data.Code, "")
|
resp, err := CreateTokenResponse(ctx, authReq, r.Client, s.provider, true, r.Data.Code, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -63,7 +137,7 @@ func (s *LegacyServer) RefreshToken(ctx context.Context, r *ClientRequest[oidc.R
|
||||||
if !ValidateGrantType(r.Client, oidc.GrantTypeRefreshToken) {
|
if !ValidateGrantType(r.Client, oidc.GrantTypeRefreshToken) {
|
||||||
return nil, oidc.ErrUnauthorizedClient()
|
return nil, oidc.ErrUnauthorizedClient()
|
||||||
}
|
}
|
||||||
request, err := RefreshTokenRequestByRefreshToken(ctx, s.op.storage, r.Data.RefreshToken)
|
request, err := RefreshTokenRequestByRefreshToken(ctx, s.provider.Storage(), r.Data.RefreshToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -73,9 +147,64 @@ func (s *LegacyServer) RefreshToken(ctx context.Context, r *ClientRequest[oidc.R
|
||||||
if err = ValidateRefreshTokenScopes(r.Data.Scopes, request); err != nil {
|
if err = ValidateRefreshTokenScopes(r.Data.Scopes, request); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resp, err := CreateTokenResponse(ctx, request, r.Client, s.op, true, "", r.Data.RefreshToken)
|
resp, err := CreateTokenResponse(ctx, request, r.Client, s.provider, true, "", r.Data.RefreshToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewResponse(resp), nil
|
return NewResponse(resp), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) JWTProfile(_ context.Context, r *Request[oidc.JWTProfileGrantRequest]) (*Response, error) {
|
||||||
|
return nil, unimplementedError(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) TokenExchange(_ context.Context, r *ClientRequest[oidc.TokenExchangeRequest]) (*Response, error) {
|
||||||
|
return nil, unimplementedError(r.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) ClientCredentialsExchange(_ context.Context, r *ClientRequest[oidc.ClientCredentialsRequest]) (*Response, error) {
|
||||||
|
return nil, unimplementedError(r.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) DeviceToken(_ context.Context, r *ClientRequest[oidc.DeviceAccessTokenRequest]) (*Response, error) {
|
||||||
|
return nil, unimplementedError(r.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) Introspect(ctx context.Context, r *ClientRequest[oidc.IntrospectionRequest]) (*Response, error) {
|
||||||
|
response := new(oidc.IntrospectionResponse)
|
||||||
|
tokenID, subject, ok := getTokenIDAndSubject(ctx, s.provider, r.Data.Token)
|
||||||
|
if !ok {
|
||||||
|
return NewResponse(response), nil
|
||||||
|
}
|
||||||
|
err := s.provider.Storage().SetIntrospectionFromToken(ctx, response, tokenID, subject, r.Client.GetID())
|
||||||
|
if err != nil {
|
||||||
|
return NewResponse(response), nil
|
||||||
|
}
|
||||||
|
response.Active = true
|
||||||
|
return NewResponse(response), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) UserInfo(ctx context.Context, r *Request[oidc.UserInfoRequest]) (*Response, error) {
|
||||||
|
tokenID, subject, ok := getTokenIDAndSubject(ctx, s.provider, r.Data.AccessToken)
|
||||||
|
if !ok {
|
||||||
|
return nil, NewStatusError(oidc.ErrAccessDenied().WithDescription("access token invalid"), http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
info := new(oidc.UserInfo)
|
||||||
|
err := s.provider.Storage().SetUserinfoFromToken(ctx, info, tokenID, subject, r.Header.Get("origin"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewStatusError(err, http.StatusForbidden)
|
||||||
|
}
|
||||||
|
return NewResponse(info), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) Revocation(_ context.Context, r *Request[oidc.RevocationRequest]) (*Response, error) {
|
||||||
|
return nil, unimplementedError(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) EndSession(_ context.Context, r *Request[oidc.EndSessionRequest]) (*Response, error) {
|
||||||
|
return nil, unimplementedError(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LegacyServer) Keys(_ context.Context, r *Request[struct{}]) (*Response, error) {
|
||||||
|
return nil, unimplementedError(r)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue