breaking change: Add GetRefreshTokenInfo() to op.Storage

This commit is contained in:
David Sharnoff 2023-02-28 15:49:24 -08:00 committed by Tim Möhlmann
parent f3eae0f329
commit f447b9b6d4
8 changed files with 59 additions and 14 deletions

View file

@ -189,6 +189,22 @@ func (mr *MockStorageMockRecorder) GetPrivateClaimsFromScopes(arg0, arg1, arg2,
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPrivateClaimsFromScopes", reflect.TypeOf((*MockStorage)(nil).GetPrivateClaimsFromScopes), arg0, arg1, arg2, arg3)
}
// GetRefreshTokenInfo mocks base method.
func (m *MockStorage) GetRefreshTokenInfo(arg0 context.Context, arg1, arg2 string) (string, string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRefreshTokenInfo", arg0, arg1, arg2)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(string)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// GetRefreshTokenInfo indicates an expected call of GetRefreshTokenInfo.
func (mr *MockStorageMockRecorder) GetRefreshTokenInfo(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRefreshTokenInfo", reflect.TypeOf((*MockStorage)(nil).GetRefreshTokenInfo), arg0, arg1, arg2)
}
// Health mocks base method.
func (m *MockStorage) Health(arg0 context.Context) error {
m.ctrl.T.Helper()

View file

@ -48,9 +48,15 @@ type AuthStorage interface {
// RevokeToken should revoke a token. In the situation that the original request was to
// revoke an access token, then tokenOrTokenID will be a tokenID and userID will be set
// but if the original request was for a refresh token, then userID will be empty and
// tokenOrTokenID will be the refresh token, not its ID.
// tokenOrTokenID will be the refresh token, not its ID. RevokeToken depends upon GetRefreshTokenInfo
// to get information from refresh tokens that are not either "<tokenID>:<userID>" strings
// nor JWTs.
RevokeToken(ctx context.Context, tokenOrTokenID string, userID string, clientID string) *oidc.Error
// GetRefreshTokenInfo must return ErrInvalidRefreshToken when presented
// with a token that is not a refresh token.
GetRefreshTokenInfo(ctx context.Context, clientID string, token string) (userID string, tokenID string, err error)
SigningKey(context.Context) (SigningKey, error)
SignatureAlgorithms(context.Context) ([]jose.SignatureAlgorithm, error)
KeySet(context.Context) ([]Key, error)
@ -100,15 +106,6 @@ type TokenExchangeTokensVerifierStorage interface {
VerifyExchangeActorToken(ctx context.Context, token string, tokenType oidc.TokenType) (tokenIDOrToken string, actor string, tokenClaims map[string]interface{}, err error)
}
// CanRefreshTokenInfo is an optional additional interface that Storage can support.
// Supporting CanRefreshTokenInfo is required to be able to (revoke) a refresh token that
// is neither an encrypted string of <tokenID>:<userID> nor a JWT.
type CanRefreshTokenInfo interface {
// GetRefreshTokenInfo must return ErrInvalidRefreshToken when presented
// with a token that is not a refresh token.
GetRefreshTokenInfo(ctx context.Context, clientID string, token string) (userID string, tokenID string, err error)
}
var ErrInvalidRefreshToken = errors.New("invalid_refresh_token")
type OPStorage interface {

View file

@ -39,8 +39,8 @@ func Revoke(w http.ResponseWriter, r *http.Request, revoker Revoker) {
}
var subject string
doDecrypt := true
if canRefreshInfo, ok := revoker.Storage().(CanRefreshTokenInfo); ok && tokenTypeHint != "access_token" {
userID, tokenID, err := canRefreshInfo.GetRefreshTokenInfo(r.Context(), clientID, token)
if tokenTypeHint != "access_token" {
userID, tokenID, err := revoker.Storage().GetRefreshTokenInfo(r.Context(), clientID, token)
if err != nil {
// An invalid refresh token means that we'll try other things (leaving doDecrypt==true)
if !errors.Is(err, ErrInvalidRefreshToken) {