新增 SimpleRefreshTokenProvider 實作 IAuthenticationTokenProvider
public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{
//實際放到DB去存起來
private static ConcurrentDictionary _refreshTokens =
new ConcurrentDictionary();
public async Task CreateAsync(AuthenticationTokenCreateContext context)
{
var guid = Guid.NewGuid().ToString();
//copy properties and set the desired lifetime of refresh token
var refreshTokenProperties = new AuthenticationProperties(context.Ticket.Properties.Dictionary)
{
IssuedUtc = context.Ticket.Properties.IssuedUtc,
//時間是3個月
ExpiresUtc = DateTime.UtcNow.AddMonths(3)
};
var refreshTokenTicket = new AuthenticationTicket(context.Ticket.Identity, refreshTokenProperties);
_refreshTokens.TryAdd(guid, refreshTokenTicket);
context.SetToken(guid);
}
public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
{
AuthenticationTicket ticket;
if (_refreshTokens.TryRemove(context.Token, out ticket))
{
context.SetTicket(ticket);
}
}
public void Create(AuthenticationTokenCreateContext context)
{
throw new NotImplementedException();
}
public void Receive(AuthenticationTokenReceiveContext context)
{
throw new NotImplementedException();
}
}
然後在 App_Start\Startup.Auth.cs 中設定 OAuthOptions 裡的RefreshTokenProvider,如下,
App_Start\Startup.Auth.cs
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
RefreshTokenProvider = new SimpleRefreshTokenProvider(),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
當我們取回 Token 時會同取得 refresh_token 的內容
再用 Refresh Token 來取得新的 Access Token 及 Refresh Token,如下
用過的 Refresh Token 會從 ConcurrentDictionary 移除。所以;之前用過的 Token 也就失效了。