Hello,
I am attempting to implement refresh tokens but my refresh request always ends up as HTTP 400 invalid_grant. This is a webapi project using OWIN and OAUTH2.
Any ideas what might be the cause?
/// <summary> /// Creates a refresh token /// </summary> /// <param name="context"> /// The authentication context /// </param> /// <returns> /// The new refresh token /// </returns> /// <exception cref="OverflowException"> /// The dictionary already contains a refresh token ticket. /// </exception> public async Task CreateAsync(AuthenticationTokenCreateContext context) { using (var ctx = new MpsDbContext()) { var refreshToken = new RefreshToken { RefreshTokenId = Guid.NewGuid(), Expires = DateTime.UtcNow.AddMinutes(5), Issued = DateTime.UtcNow, ProtectedTicket = context.SerializeTicket(), Subject = context.Ticket.Identity.Name }; context.Ticket.Properties.IssuedUtc = refreshToken.Issued; context.Ticket.Properties.ExpiresUtc = refreshToken.Expires; ctx.RefreshTokens.Add(refreshToken); await ctx.SaveChangesAsync(); context.SetToken(refreshToken.RefreshTokenId.ToString()); } } /// <summary> /// Validates a refresh token /// </summary> /// <param name="context"> /// The authentication context /// </param> /// <returns> /// Nothing is returned /// </returns> public async Task ReceiveAsync(AuthenticationTokenReceiveContext context) { using (var ctx = new MpsDbContext()) { var clientRefreshToken = Guid.Parse(context.Token); var result = from n in ctx.RefreshTokens where n.RefreshTokenId.Equals(clientRefreshToken) select n; var refreshToken = result.First(); if (refreshToken != null) { context.DeserializeTicket(refreshToken.ProtectedTicket); ctx.RefreshTokens.Remove(refreshToken); await ctx.SaveChangesAsync(); } } } /// <summary> /// Create a refresh token /// </summary> /// <param name="context"> /// The request context. /// </param> /// <exception cref="NotImplementedException"> /// Synchronous operation not allowed /// </exception> public void Create(AuthenticationTokenCreateContext context) { throw new NotImplementedException(); } /// <summary> /// Validate a refresh token /// </summary> /// <param name="context"> /// The request context. /// </param> /// <exception cref="NotImplementedException"> /// Synchronous operation not allowed /// </exception> public void Receive(AuthenticationTokenReceiveContext context) { throw new NotImplementedException(); }
public override async Task GrantRefreshToken(OAuthGrantRefreshTokenContext context) { var newId = new ClaimsIdentity(context.Ticket.Identity); var newTicket = new AuthenticationTicket(newId, context.Ticket.Properties); context.Validated(newTicket); }
refreshToken = function () { var postData = {"grant_type": "refresh_token","refresh_token": sessionStorage.getItem("MpsRefreshToken") };$.ajax( { url: "token", type: "POST", crossDomain: false, data: postData, headers: {"Authorization": sessionStorage.getItem("MpsAuthToken") }, success: function (data, textStatus, jqXHR) { sessionStorage.clear(); sessionStorage.setItem("MpsAuthToken", "Bearer " + data.access_token); sessionStorage.setItem("MpsRefreshToken", data.refresh_token); sessionStorage.setItem("MpsUserName", data.userName); sessionStorage.setItem("MpsUserId", data.userId); sessionStorage.setItem("MpsUserEmail", data.userEmail); sessionStorage.setItem("TokenExpires", data[".expires"]); sessionStorage.setItem("TokenLifeSpan", data.expires_in); tokenLifeSpan = parseInt(sessionStorage.getItem("TokenLifeSpan")); timer = window.setInterval(checkTokenExpired, 30000); }, error: function (jqXHR, textStatus, errorThrown) { window.alert("error"); } }); }
POST http://localhost/mps/token HTTP/1.1 Accept: */* Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Authorization: Bearer hNlwBHqUbKYPRz41rriwGKG9x6G5MD-uCWX5ftYTM8P-8MeQ7qXB7xtn0KeIVKBP3jUDMQVenB4LgBMOkrq1Cn9bkt_jIqQv-rUEr8eyJ67kxxQ5kHKMbzcsjl4jgeyIEJxQe9efhFf2LoZ9pPIdbfkKfKG4BUUMpvRmHHbzju-X20Ok9CzEDSE-KPKv2i9vpsuI9391uprHFkluzP-58jL8GNH3al7KkgYRCb9syANsCq6MY1s5Hhj0UrYwIOPP5tNs2MO0wNVOg86uH1qxBl1zof24aF1TQzJ6KCRHKyxFmyUj3aEd0HTAsyvHAUx-KAi7miwMyzfzkSc7nodlYwSeXPLd2FMQffQMQwUOdGZo_ol03cib294--yg5WOWCGEqWCIHcrl6WauJ9_e4MGudD3VzGqmV1VeuPJV9lHGZ-KiyepnVVbd0IemMCTQBg5dbNgaUQa6Hab3IWev_J9O9gs01UrhMuqTfyuNZ6wv7S1_477MMC_OfkKLqykS6ZMRhqoOzyb2afMwWbxM7pYCpxHO20-8ys9sKCvhVQLFW4LnPdmYvuaMgJMLWxNUS2oNggh-Ro3jLAYfxiElrjNN0fvDK7ouOO16wv-bxgSzoVwCwPdK0XW6Ejj9pjc-QoJb0HBnsXHyURyYxEgK0KTPesCCs X-Requested-With: XMLHttpRequest Referer: http://localhost/mps/default.htm Accept-Language: en-GB,en;q=0.5 Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko Connection: Keep-Alive Content-Length: 75 DNT: 1 Host: localhost Pragma: no-cache grant_type=refresh_token&refresh_token=03f325d3-3635-e511-8266-4c8d79e0337d