2023-06-22 22:12:33 +00:00
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
2020-12-01 19:01:23 +00:00
// SPDX-License-Identifier: Apache-2.0
2023-06-22 22:12:33 +00:00
package storage
2020-12-01 19:01:23 +00:00
import (
"context"
"time"
"github.com/ory/fosite"
"github.com/ory/fosite/handler/oauth2"
2020-12-02 01:18:32 +00:00
"github.com/ory/fosite/handler/openid"
fositepkce "github.com/ory/fosite/handler/pkce"
2020-12-01 19:01:23 +00:00
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
2022-07-14 16:51:11 +00:00
"go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/config/v1alpha1"
2023-06-22 22:12:33 +00:00
"go.pinniped.dev/internal/federationdomain/clientregistry"
"go.pinniped.dev/internal/federationdomain/timeouts"
2020-12-04 22:31:06 +00:00
"go.pinniped.dev/internal/fositestorage/accesstoken"
2020-12-01 19:01:23 +00:00
"go.pinniped.dev/internal/fositestorage/authorizationcode"
2020-12-02 01:18:32 +00:00
"go.pinniped.dev/internal/fositestorage/openidconnect"
"go.pinniped.dev/internal/fositestorage/pkce"
2020-12-04 22:31:06 +00:00
"go.pinniped.dev/internal/fositestorage/refreshtoken"
2021-04-09 00:28:01 +00:00
"go.pinniped.dev/internal/fositestoragei"
2022-07-14 16:51:11 +00:00
"go.pinniped.dev/internal/oidcclientsecretstorage"
2020-12-01 19:01:23 +00:00
)
type KubeStorage struct {
2021-06-15 16:27:30 +00:00
clientManager fosite . ClientManager
2020-12-01 19:01:23 +00:00
authorizationCodeStorage oauth2 . AuthorizeCodeStorage
2020-12-01 22:53:22 +00:00
pkceStorage fositepkce . PKCERequestStorage
2020-12-02 01:18:32 +00:00
oidcStorage openid . OpenIDConnectRequestStorage
2020-12-04 22:31:06 +00:00
accessTokenStorage accesstoken . RevocationStorage
refreshTokenStorage refreshtoken . RevocationStorage
2020-12-01 19:01:23 +00:00
}
2021-04-09 00:28:01 +00:00
var _ fositestoragei . AllFositeStorage = & KubeStorage { }
2022-07-20 20:55:56 +00:00
func NewKubeStorage (
secrets corev1client . SecretInterface ,
oidcClientsClient v1alpha1 . OIDCClientInterface ,
2023-06-22 22:12:33 +00:00
timeoutsConfiguration timeouts . Configuration ,
2022-07-20 20:55:56 +00:00
minBcryptCost int ,
) * KubeStorage {
2020-12-10 22:47:58 +00:00
nowFunc := time . Now
2020-12-01 22:53:22 +00:00
return & KubeStorage {
2022-08-26 17:57:45 +00:00
clientManager : clientregistry . NewClientManager ( oidcClientsClient , oidcclientsecretstorage . New ( secrets ) , minBcryptCost ) ,
2020-12-10 22:47:58 +00:00
authorizationCodeStorage : authorizationcode . New ( secrets , nowFunc , timeoutsConfiguration . AuthorizationCodeSessionStorageLifetime ) ,
pkceStorage : pkce . New ( secrets , nowFunc , timeoutsConfiguration . PKCESessionStorageLifetime ) ,
oidcStorage : openidconnect . New ( secrets , nowFunc , timeoutsConfiguration . OIDCSessionStorageLifetime ) ,
accessTokenStorage : accesstoken . New ( secrets , nowFunc , timeoutsConfiguration . AccessTokenSessionStorageLifetime ) ,
refreshTokenStorage : refreshtoken . New ( secrets , nowFunc , timeoutsConfiguration . RefreshTokenSessionStorageLifetime ) ,
2020-12-01 22:53:22 +00:00
}
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
//
// Authorization Code sessions:
//
// These are keyed by the signature of the authcode.
//
// Fosite will create these in the authorize endpoint.
//
// Fosite will never delete them. Instead, it wants to mark them as invalidated once the authcode is used to redeem tokens.
// That way, it can later detect the case where an authcode that was already redeemed gets used again.
//
func ( k KubeStorage ) CreateAuthorizeCodeSession ( ctx context . Context , signatureOfAuthcode string , r fosite . Requester ) ( err error ) {
return k . authorizationCodeStorage . CreateAuthorizeCodeSession ( ctx , signatureOfAuthcode , r )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) GetAuthorizeCodeSession ( ctx context . Context , signatureOfAuthcode string , s fosite . Session ) ( request fosite . Requester , err error ) {
return k . authorizationCodeStorage . GetAuthorizeCodeSession ( ctx , signatureOfAuthcode , s )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) InvalidateAuthorizeCodeSession ( ctx context . Context , signatureOfAuthcode string ) ( err error ) {
return k . authorizationCodeStorage . InvalidateAuthorizeCodeSession ( ctx , signatureOfAuthcode )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
//
// PKCE sessions:
//
// These are keyed by the signature of the authcode.
//
// Fosite will create these in the authorize endpoint at the same time that it is creating an authcode.
//
// Fosite will delete these in the token endpoint during authcode redemption since they are no longer needed after that.
// If the user chooses to never redeem their authcode, then fosite will never delete these.
//
func ( k KubeStorage ) CreatePKCERequestSession ( ctx context . Context , signatureOfAuthcode string , requester fosite . Requester ) error {
return k . pkceStorage . CreatePKCERequestSession ( ctx , signatureOfAuthcode , requester )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) GetPKCERequestSession ( ctx context . Context , signatureOfAuthcode string , session fosite . Session ) ( fosite . Requester , error ) {
return k . pkceStorage . GetPKCERequestSession ( ctx , signatureOfAuthcode , session )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) DeletePKCERequestSession ( ctx context . Context , signatureOfAuthcode string ) error {
return k . pkceStorage . DeletePKCERequestSession ( ctx , signatureOfAuthcode )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
//
// OpenID Connect sessions:
//
// These are keyed by the full value of the authcode (not just the signature).
//
// Fosite will create these in the authorize endpoint when it creates an authcode, but only if the user
// requested the openid scope.
//
// Fosite will never delete these, which is likely a bug in fosite. Although there is a delete method below, fosite
// never calls it. Used during authcode redemption, they will never be accessed again after a successful authcode
// redemption. Although that implies that they should probably follow a lifecycle similar the the PKCE storage, they
// are, in fact, not deleted.
//
func ( k KubeStorage ) CreateOpenIDConnectSession ( ctx context . Context , fullAuthcode string , requester fosite . Requester ) error {
return k . oidcStorage . CreateOpenIDConnectSession ( ctx , fullAuthcode , requester )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) GetOpenIDConnectSession ( ctx context . Context , fullAuthcode string , requester fosite . Requester ) ( fosite . Requester , error ) {
return k . oidcStorage . GetOpenIDConnectSession ( ctx , fullAuthcode , requester )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) DeleteOpenIDConnectSession ( ctx context . Context , fullAuthcode string ) error {
2022-08-24 21:45:55 +00:00
return k . oidcStorage . DeleteOpenIDConnectSession ( ctx , fullAuthcode ) //nolint:staticcheck // we know this is deprecated and never called. our GC controller cleans these up.
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
//
// Access token sessions:
//
// These are keyed by the signature of the access token.
//
// Fosite will create these in the token endpoint whenever it wants to hand out an access token, including the original
// authcode redemption and also during refresh.
//
// Fosite will not use the delete method. Instead, it will use the revoke method to delete them.
// During a refresh in the token endpoint, the old access token is revoked just before the new access token is created.
// Also, if the token endpoint receives an authcode that was already used successfully, then it revokes the access token
// that was previously handed out for that authcode. If a user stops coming back to refresh their tokens, then that
// access token will never be deleted.
//
func ( k KubeStorage ) CreateAccessTokenSession ( ctx context . Context , signatureOfAccessToken string , requester fosite . Requester ) ( err error ) {
return k . accessTokenStorage . CreateAccessTokenSession ( ctx , signatureOfAccessToken , requester )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) GetAccessTokenSession ( ctx context . Context , signatureOfAccessToken string , session fosite . Session ) ( request fosite . Requester , err error ) {
return k . accessTokenStorage . GetAccessTokenSession ( ctx , signatureOfAccessToken , session )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) DeleteAccessTokenSession ( ctx context . Context , signatureOfAccessToken string ) ( err error ) {
return k . accessTokenStorage . DeleteAccessTokenSession ( ctx , signatureOfAccessToken )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) RevokeAccessToken ( ctx context . Context , requestID string ) error {
return k . accessTokenStorage . RevokeAccessToken ( ctx , requestID )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
//
// Refresh token sessions:
//
// These are keyed by the signature of the refresh token.
//
// Fosite will create these in the token endpoint whenever it wants to hand out an refresh token, including the original
// authcode redemption and also during refresh. Refresh tokens are only handed out when the user requested the
// offline_access scope on the original authorization request.
//
// Fosite will not use the delete method. Instead, it will use the revoke method to delete them.
// During a refresh in the token endpoint, the old refresh token is revoked just before the new refresh token is created.
// Also, if the token endpoint receives an authcode that was already used successfully, then it revokes the refresh token
// that was previously handed out for that authcode. If a user stops coming back to refresh their tokens, then that
// refresh token will never be deleted.
//
func ( k KubeStorage ) CreateRefreshTokenSession ( ctx context . Context , signatureOfRefreshToken string , request fosite . Requester ) ( err error ) {
return k . refreshTokenStorage . CreateRefreshTokenSession ( ctx , signatureOfRefreshToken , request )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) GetRefreshTokenSession ( ctx context . Context , signatureOfRefreshToken string , session fosite . Session ) ( request fosite . Requester , err error ) {
return k . refreshTokenStorage . GetRefreshTokenSession ( ctx , signatureOfRefreshToken , session )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) DeleteRefreshTokenSession ( ctx context . Context , signatureOfRefreshToken string ) ( err error ) {
return k . refreshTokenStorage . DeleteRefreshTokenSession ( ctx , signatureOfRefreshToken )
2020-12-01 19:01:23 +00:00
}
2020-12-08 19:47:39 +00:00
func ( k KubeStorage ) RevokeRefreshToken ( ctx context . Context , requestID string ) error {
return k . refreshTokenStorage . RevokeRefreshToken ( ctx , requestID )
2020-12-01 19:01:23 +00:00
}
2022-01-19 21:57:01 +00:00
func ( k KubeStorage ) RevokeRefreshTokenMaybeGracePeriod ( ctx context . Context , requestID string , signature string ) error {
return k . refreshTokenStorage . RevokeRefreshTokenMaybeGracePeriod ( ctx , requestID , signature )
}
2020-12-08 19:47:39 +00:00
//
// OAuth client definitions:
//
2021-06-15 16:27:30 +00:00
func ( k KubeStorage ) GetClient ( ctx context . Context , id string ) ( fosite . Client , error ) {
return k . clientManager . GetClient ( ctx , id )
2020-12-01 19:01:23 +00:00
}
2021-06-15 16:27:30 +00:00
func ( k KubeStorage ) ClientAssertionJWTValid ( ctx context . Context , jti string ) error {
return k . clientManager . ClientAssertionJWTValid ( ctx , jti )
2020-12-01 19:01:23 +00:00
}
2021-06-15 16:27:30 +00:00
func ( k KubeStorage ) SetClientAssertionJWT ( ctx context . Context , jti string , exp time . Time ) error {
return k . clientManager . SetClientAssertionJWT ( ctx , jti , exp )
2020-12-01 19:01:23 +00:00
}