(ctx context.Context, args *IssueTokenArgs)
| 234 | } |
| 235 | |
| 236 | func (t *tokenAuth) Issue(ctx context.Context, args *IssueTokenArgs) (*Token, error) { |
| 237 | u := args.User |
| 238 | rootTokenID := args.RootTokenID |
| 239 | |
| 240 | uidEncoded := hashid.EncodeUserID(t.idEncoder, u.ID) |
| 241 | tokenSettings := t.s.TokenAuth(ctx) |
| 242 | issueDate := time.Now() |
| 243 | accessTokenExpired := time.Now().Add(tokenSettings.AccessTokenTTL) |
| 244 | refreshTokenExpired := time.Now().Add(tokenSettings.RefreshTokenTTL) |
| 245 | if args.RefreshTTLOverride > 0 { |
| 246 | refreshTokenExpired = time.Now().Add(args.RefreshTTLOverride) |
| 247 | } |
| 248 | if rootTokenID == nil { |
| 249 | newRootTokenID := uuid.Must(uuid.NewV4()) |
| 250 | rootTokenID = &newRootTokenID |
| 251 | } |
| 252 | |
| 253 | accessToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, Claims{ |
| 254 | TokenType: TokenTypeAccess, |
| 255 | RegisteredClaims: jwt.RegisteredClaims{ |
| 256 | Subject: uidEncoded, |
| 257 | NotBefore: jwt.NewNumericDate(issueDate), |
| 258 | ExpiresAt: jwt.NewNumericDate(accessTokenExpired), |
| 259 | }, |
| 260 | ClientID: args.ClientID, |
| 261 | Scopes: args.Scopes, |
| 262 | }).SignedString(t.secret) |
| 263 | if err != nil { |
| 264 | return nil, fmt.Errorf("faield to sign access token: %w", err) |
| 265 | } |
| 266 | |
| 267 | userHash := t.hashUserState(ctx, u) |
| 268 | refreshToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, Claims{ |
| 269 | TokenType: TokenTypeRefresh, |
| 270 | RootTokenID: rootTokenID, |
| 271 | RegisteredClaims: jwt.RegisteredClaims{ |
| 272 | Subject: uidEncoded, |
| 273 | NotBefore: jwt.NewNumericDate(issueDate), |
| 274 | ExpiresAt: jwt.NewNumericDate(refreshTokenExpired), |
| 275 | }, |
| 276 | Scopes: args.Scopes, |
| 277 | ClientID: args.ClientID, |
| 278 | StateHash: userHash[:], |
| 279 | }).SignedString(t.secret) |
| 280 | if err != nil { |
| 281 | return nil, fmt.Errorf("faield to sign refresh token: %w", err) |
| 282 | } |
| 283 | |
| 284 | return &Token{ |
| 285 | AccessToken: accessToken, |
| 286 | RefreshToken: refreshToken, |
| 287 | AccessExpires: accessTokenExpired, |
| 288 | RefreshExpires: refreshTokenExpired, |
| 289 | UID: u.ID, |
| 290 | }, nil |
| 291 | } |
| 292 | |
| 293 | // hashUserState returns a hash string for user state for critical fields, it is used |
no test coverage detected