parent
9d12d1d900
commit
3a16504990
4 changed files with 116 additions and 5 deletions
|
@ -39,7 +39,7 @@ type AuthRequest struct {
|
|||
CodeChallenge *OIDCCodeChallenge
|
||||
|
||||
done bool
|
||||
authTime time.Time
|
||||
AuthTime time.Time
|
||||
}
|
||||
|
||||
// LogValue allows you to define which fields will be logged.
|
||||
|
@ -76,7 +76,7 @@ func (a *AuthRequest) GetAudience() []string {
|
|||
}
|
||||
|
||||
func (a *AuthRequest) GetAuthTime() time.Time {
|
||||
return a.authTime
|
||||
return a.AuthTime
|
||||
}
|
||||
|
||||
func (a *AuthRequest) GetClientID() string {
|
||||
|
|
|
@ -771,7 +771,7 @@ func (s *Storage) getTokenExchangeClaims(ctx context.Context, request op.TokenEx
|
|||
func getInfoFromRequest(req op.TokenRequest) (clientID string, authTime time.Time, amr []string) {
|
||||
authReq, ok := req.(*AuthRequest) // Code Flow (with scope offline_access)
|
||||
if ok {
|
||||
return authReq.ApplicationID, authReq.authTime, authReq.GetAMR()
|
||||
return authReq.ApplicationID, authReq.AuthTime, authReq.GetAMR()
|
||||
}
|
||||
refreshReq, ok := req.(*RefreshTokenRequest) // Refresh Token Request
|
||||
if ok {
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
|
||||
httphelper "github.com/zitadel/oidc/v3/pkg/http"
|
||||
"github.com/zitadel/oidc/v3/pkg/oidc"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
type DeviceAuthorizationConfig struct {
|
||||
|
@ -291,15 +292,27 @@ func CheckDeviceAuthorizationState(ctx context.Context, clientID, deviceCode str
|
|||
}
|
||||
|
||||
func CreateDeviceTokenResponse(ctx context.Context, tokenRequest TokenRequest, creator TokenCreator, client Client) (*oidc.AccessTokenResponse, error) {
|
||||
ctx, span := tracer.Start(ctx, "CreateDeviceTokenResponse")
|
||||
defer span.End()
|
||||
|
||||
accessToken, refreshToken, validity, err := CreateAccessToken(ctx, tokenRequest, client.AccessTokenType(), creator, client, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &oidc.AccessTokenResponse{
|
||||
response := &oidc.AccessTokenResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
TokenType: oidc.BearerToken,
|
||||
ExpiresIn: uint64(validity.Seconds()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
if idTokenRequest, ok := tokenRequest.(IDTokenRequest); ok && slices.Contains(tokenRequest.GetScopes(), oidc.ScopeOpenID) {
|
||||
response.IDToken, err = CreateIDToken(ctx, IssuerFromContext(ctx), idTokenRequest, client.IDTokenLifetime(), accessToken, "", creator.Storage(), client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
|
|
@ -453,3 +453,101 @@ func TestCheckDeviceAuthorizationState(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateDeviceTokenResponse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
tokenRequest op.TokenRequest
|
||||
wantAccessToken bool
|
||||
wantRefreshToken bool
|
||||
wantIDToken bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "access token",
|
||||
tokenRequest: &storage.AuthRequest{
|
||||
ID: "auth1",
|
||||
AuthTime: time.Now(),
|
||||
ApplicationID: "app1",
|
||||
ResponseType: oidc.ResponseTypeCode,
|
||||
UserID: "id1",
|
||||
},
|
||||
wantAccessToken: true,
|
||||
},
|
||||
{
|
||||
name: "access and refresh tokens",
|
||||
tokenRequest: &storage.AuthRequest{
|
||||
ID: "auth1",
|
||||
AuthTime: time.Now(),
|
||||
ApplicationID: "app1",
|
||||
ResponseType: oidc.ResponseTypeCode,
|
||||
UserID: "id1",
|
||||
Scopes: []string{oidc.ScopeOfflineAccess},
|
||||
},
|
||||
wantAccessToken: true,
|
||||
wantRefreshToken: true,
|
||||
},
|
||||
{
|
||||
name: "access and id token",
|
||||
tokenRequest: &storage.AuthRequest{
|
||||
ID: "auth1",
|
||||
AuthTime: time.Now(),
|
||||
ApplicationID: "app1",
|
||||
ResponseType: oidc.ResponseTypeCode,
|
||||
UserID: "id1",
|
||||
Scopes: []string{oidc.ScopeOpenID},
|
||||
},
|
||||
wantAccessToken: true,
|
||||
wantIDToken: true,
|
||||
},
|
||||
{
|
||||
name: "access, refresh and id token",
|
||||
tokenRequest: &storage.AuthRequest{
|
||||
ID: "auth1",
|
||||
AuthTime: time.Now(),
|
||||
ApplicationID: "app1",
|
||||
ResponseType: oidc.ResponseTypeCode,
|
||||
UserID: "id1",
|
||||
Scopes: []string{oidc.ScopeOfflineAccess, oidc.ScopeOpenID},
|
||||
},
|
||||
wantAccessToken: true,
|
||||
wantRefreshToken: true,
|
||||
wantIDToken: true,
|
||||
},
|
||||
{
|
||||
name: "id token creation error",
|
||||
tokenRequest: &storage.AuthRequest{
|
||||
ID: "auth1",
|
||||
AuthTime: time.Now(),
|
||||
ApplicationID: "app1",
|
||||
ResponseType: oidc.ResponseTypeCode,
|
||||
UserID: "foobar",
|
||||
Scopes: []string{oidc.ScopeOfflineAccess, oidc.ScopeOpenID},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client, err := testProvider.Storage().GetClientByClientID(context.Background(), "native")
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := op.CreateDeviceTokenResponse(context.Background(), tt.tokenRequest, testProvider, client)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
assert.InDelta(t, 300, got.ExpiresIn, 2)
|
||||
if tt.wantAccessToken {
|
||||
assert.NotEmpty(t, got.AccessToken, "access token")
|
||||
}
|
||||
if tt.wantRefreshToken {
|
||||
assert.NotEmpty(t, got.RefreshToken, "refresh token")
|
||||
}
|
||||
if tt.wantIDToken {
|
||||
assert.NotEmpty(t, got.IDToken, "id token")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue