RefreshTokenGrant implements the refresh_token grant type flow
(ctx context.Context, w http.ResponseWriter, r *http.Request)
| 103 | |
| 104 | // RefreshTokenGrant implements the refresh_token grant type flow |
| 105 | func (a *API) RefreshTokenGrant(ctx context.Context, w http.ResponseWriter, r *http.Request) error { |
| 106 | config := a.getConfig(ctx) |
| 107 | instanceID := getInstanceID(ctx) |
| 108 | tokenStr := r.FormValue("refresh_token") |
| 109 | cookie := r.Header.Get(useCookieHeader) |
| 110 | |
| 111 | if tokenStr == "" { |
| 112 | return oauthError("invalid_request", "refresh_token required") |
| 113 | } |
| 114 | |
| 115 | user, token, err := models.FindUserWithRefreshToken(a.db, tokenStr) |
| 116 | if err != nil { |
| 117 | if models.IsNotFoundError(err) { |
| 118 | return oauthError("invalid_grant", "Invalid Refresh Token") |
| 119 | } |
| 120 | return internalServerError(err.Error()) |
| 121 | } |
| 122 | |
| 123 | if token.Revoked { |
| 124 | a.clearCookieToken(ctx, w) |
| 125 | return oauthError("invalid_grant", "Invalid Refresh Token").WithInternalMessage("Possible abuse attempt: %v", r) |
| 126 | } |
| 127 | |
| 128 | var tokenString string |
| 129 | var newToken *models.RefreshToken |
| 130 | |
| 131 | err = a.db.Transaction(func(tx *storage.Connection) error { |
| 132 | var terr error |
| 133 | if terr = models.NewAuditLogEntry(tx, instanceID, user, models.TokenRefreshedAction, nil); terr != nil { |
| 134 | return terr |
| 135 | } |
| 136 | |
| 137 | newToken, terr = models.GrantRefreshTokenSwap(tx, user, token) |
| 138 | if terr != nil { |
| 139 | return internalServerError(terr.Error()) |
| 140 | } |
| 141 | |
| 142 | tokenString, terr = generateAccessToken(user, time.Second*time.Duration(config.JWT.Exp), config.JWT.Secret) |
| 143 | if terr != nil { |
| 144 | return internalServerError("error generating jwt token").WithInternalError(terr) |
| 145 | } |
| 146 | |
| 147 | if cookie != "" && config.Cookie.Duration > 0 { |
| 148 | if terr = a.setCookieToken(config, tokenString, cookie == useSessionCookie, w); terr != nil { |
| 149 | return internalServerError("Failed to set JWT cookie. %s", terr) |
| 150 | } |
| 151 | } |
| 152 | return nil |
| 153 | }) |
| 154 | if err != nil { |
| 155 | return err |
| 156 | } |
| 157 | metering.RecordLogin("token", user.ID, instanceID) |
| 158 | return sendJSON(w, http.StatusOK, &AccessTokenResponse{ |
| 159 | Token: tokenString, |
| 160 | TokenType: "bearer", |
| 161 | ExpiresIn: config.JWT.Exp, |
| 162 | RefreshToken: newToken.Token, |
no test coverage detected