(c *gin.Context, refreshToken string, reqClientId string)
| 517 | } |
| 518 | |
| 519 | func (service *OIDCService) RefreshAccessToken(c *gin.Context, refreshToken string, reqClientId string) (TokenResponse, error) { |
| 520 | entry, err := service.queries.GetOidcTokenByRefreshToken(c, service.Hash(refreshToken)) |
| 521 | |
| 522 | if err != nil { |
| 523 | if err == sql.ErrNoRows { |
| 524 | return TokenResponse{}, ErrTokenNotFound |
| 525 | } |
| 526 | return TokenResponse{}, err |
| 527 | } |
| 528 | |
| 529 | if entry.RefreshTokenExpiresAt < time.Now().Unix() { |
| 530 | return TokenResponse{}, ErrTokenExpired |
| 531 | } |
| 532 | |
| 533 | // Ensure the client ID in the request matches the client ID in the token |
| 534 | if entry.ClientID != reqClientId { |
| 535 | return TokenResponse{}, ErrInvalidClient |
| 536 | } |
| 537 | |
| 538 | user, err := service.GetUserinfo(c, entry.Sub) |
| 539 | |
| 540 | if err != nil { |
| 541 | return TokenResponse{}, err |
| 542 | } |
| 543 | |
| 544 | idToken, err := service.generateIDToken(config.OIDCClientConfig{ |
| 545 | ClientID: entry.ClientID, |
| 546 | }, user, entry.Scope, entry.Nonce) |
| 547 | |
| 548 | if err != nil { |
| 549 | return TokenResponse{}, err |
| 550 | } |
| 551 | |
| 552 | accessToken := utils.GenerateString(32) |
| 553 | newRefreshToken := utils.GenerateString(32) |
| 554 | |
| 555 | tokenExpiresAt := time.Now().Add(time.Duration(service.config.SessionExpiry) * time.Second).Unix() |
| 556 | refrshTokenExpiresAt := time.Now().Add(time.Duration(service.config.SessionExpiry*2) * time.Second).Unix() |
| 557 | |
| 558 | tokenResponse := TokenResponse{ |
| 559 | AccessToken: accessToken, |
| 560 | RefreshToken: newRefreshToken, |
| 561 | TokenType: "Bearer", |
| 562 | ExpiresIn: int64(service.config.SessionExpiry), |
| 563 | IDToken: idToken, |
| 564 | Scope: strings.ReplaceAll(entry.Scope, ",", " "), |
| 565 | } |
| 566 | |
| 567 | _, err = service.queries.UpdateOidcTokenByRefreshToken(c, repository.UpdateOidcTokenByRefreshTokenParams{ |
| 568 | AccessTokenHash: service.Hash(accessToken), |
| 569 | RefreshTokenHash: service.Hash(newRefreshToken), |
| 570 | TokenExpiresAt: tokenExpiresAt, |
| 571 | RefreshTokenExpiresAt: refrshTokenExpiresAt, |
| 572 | RefreshTokenHash_2: service.Hash(refreshToken), // that's the selector, it's not stored in the db |
| 573 | }) |
| 574 | |
| 575 | if err != nil { |
| 576 | return TokenResponse{}, err |
no test coverage detected