[ASP.NET]Web API 加入 Refresh Token

本篇介紹使用簡單的 Refresh Token 機制

預設的 Web API 專案中並沒有提供 Refresh Token 的範例。

網路上「OWIN Security - How to Implement OAuth2 Refresh Tokens」提供一個簡單的實作,

它是用透過 GUID 來當Key值,並將值存放在 ConcurrentDictionary<string, AuthenticationTicket> 之中。

拿「Web API bearer token 驗證」的範例,再加入 Refresh Token 的實作。

新增 SimpleRefreshTokenProvider 實作 IAuthenticationTokenProvider ,如下,


public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{
	//實際放到DB去存起來
	private static ConcurrentDictionary<string, AuthenticationTicket> _refreshTokens = 
		new ConcurrentDictionary<string, AuthenticationTicket>();

	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,如下,


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
};

 

Controllers裡的ValuesController.cs 可以多傳出 User 的資訊,如下,


public IEnumerable<string> Get()
{
	return new string[] { "value1", "value2", User.Identity.Name };
}

 

建置執行,然後就可以用 Fiddler 來測試它。

1.取得 Access Token 及 Refresh Token,如下,

使用 POST , Request Body如下,

grant_type=password&username=rainmaker&password=rainmaker

image

image

 

2.再用 Refresh Token 來取得新的 Access Token 及 Refresh Token,如下,

拿上面取得的 Refresh Token 再取得新的,grant_type則使用 refresh_token,

使用 POST , Request Body如下,

grant_type=refresh_token&refresh_token=cc1ce9fd-ede5-4d19-b2d1-626856ef5dd6

image

image

 

用過的 Refresh Token 會從 ConcurrentDictionary 移除,所以再執行 Step 2 會失敗,如下,

image

 

3.用 access_token 去取 ValuesController 的資料,如下,

使用 GET,URL為  http://localhost:51528/api/values

Header加入,Authorization:Bearer [access token]

image

image

 

參考資料

OWIN Security - How to Implement OAuth2 Refresh Tokens

Web API bearer token 驗證

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^