107 lines
3.1 KiB
Go
107 lines
3.1 KiB
Go
package op
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/caos/oidc/pkg/oidc"
|
|
)
|
|
|
|
type TokenCreator interface {
|
|
Issuer() string
|
|
Signer() Signer
|
|
Storage() Storage
|
|
Crypto() Crypto
|
|
}
|
|
|
|
func CreateTokenResponse(ctx context.Context, authReq AuthRequest, client Client, creator TokenCreator, createAccessToken bool, code string) (*oidc.AccessTokenResponse, error) {
|
|
var accessToken string
|
|
var validity time.Duration
|
|
if createAccessToken {
|
|
var err error
|
|
accessToken, validity, err = CreateAccessToken(ctx, authReq, client, creator)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
idToken, err := CreateIDToken(ctx, creator.Issuer(), authReq, client.IDTokenLifetime(), accessToken, code, creator.Storage(), creator.Signer())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
exp := uint64(validity.Seconds())
|
|
return &oidc.AccessTokenResponse{
|
|
AccessToken: accessToken,
|
|
IDToken: idToken,
|
|
TokenType: oidc.BearerToken,
|
|
ExpiresIn: exp,
|
|
}, nil
|
|
}
|
|
|
|
func CreateAccessToken(ctx context.Context, authReq AuthRequest, client Client, creator TokenCreator) (token string, validity time.Duration, err error) {
|
|
id, exp, err := creator.Storage().CreateToken(ctx, authReq)
|
|
if err != nil {
|
|
return "", 0, err
|
|
}
|
|
validity = exp.Sub(time.Now().UTC())
|
|
if client.AccessTokenType() == AccessTokenTypeJWT {
|
|
token, err = CreateJWT(creator.Issuer(), authReq, exp, id, creator.Signer())
|
|
return
|
|
}
|
|
token, err = CreateBearerToken(id, creator.Crypto())
|
|
return
|
|
}
|
|
|
|
func CreateBearerToken(id string, crypto Crypto) (string, error) {
|
|
return crypto.Encrypt(id)
|
|
}
|
|
|
|
func CreateJWT(issuer string, authReq AuthRequest, exp time.Time, id string, signer Signer) (string, error) {
|
|
now := time.Now().UTC()
|
|
nbf := now
|
|
claims := &oidc.AccessTokenClaims{
|
|
Issuer: issuer,
|
|
Subject: authReq.GetSubject(),
|
|
Audiences: authReq.GetAudience(),
|
|
Expiration: exp,
|
|
IssuedAt: now,
|
|
NotBefore: nbf,
|
|
JWTID: id,
|
|
}
|
|
return signer.SignAccessToken(claims)
|
|
}
|
|
|
|
func CreateIDToken(ctx context.Context, issuer string, authReq AuthRequest, validity time.Duration, accessToken, code string, storage Storage, signer Signer) (string, error) {
|
|
var err error
|
|
exp := time.Now().UTC().Add(validity)
|
|
userinfo, err := storage.GetUserinfoFromScopes(ctx, authReq.GetSubject(), authReq.GetScopes())
|
|
if err != nil {
|
|
|
|
}
|
|
claims := &oidc.IDTokenClaims{
|
|
Issuer: issuer,
|
|
Audiences: authReq.GetAudience(),
|
|
Expiration: exp,
|
|
IssuedAt: time.Now().UTC(),
|
|
AuthTime: authReq.GetAuthTime(),
|
|
Nonce: authReq.GetNonce(),
|
|
AuthenticationContextClassReference: authReq.GetACR(),
|
|
AuthenticationMethodsReferences: authReq.GetAMR(),
|
|
AuthorizedParty: authReq.GetClientID(),
|
|
Userinfo: *userinfo,
|
|
}
|
|
if accessToken != "" {
|
|
claims.AccessTokenHash, err = oidc.ClaimHash(accessToken, signer.SignatureAlgorithm())
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
if code != "" {
|
|
claims.CodeHash, err = oidc.ClaimHash(code, signer.SignatureAlgorithm())
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
return signer.SignIDToken(claims)
|
|
}
|