How to write OAuth2 Web API Client in Asp.net MVC
To support the client credentials grant type, your best option is probably to directly use HttpClient
:
var request = new HttpRequestMessage(HttpMethod.Post, "http://server.com/token");
request.Content = new FormUrlEncodedContent(new Dictionary<string, string> {
{ "client_id", "your client_id" },
{ "client_secret", "your client_secret" },
{ "grant_type", "client_credentials" }
});
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
var token = payload.Value<string>("access_token");
For interactive flows (like the authorization code flow), there are two better approaches:
If your authorization server supports OpenID Connect (which is based on OAuth2), you can simply use the OpenID Connect middleware for OWIN/Katana 3 developed by Microsoft: https://www.nuget.org/packages/Microsoft.Owin.Security.OpenIdConnect/
If OpenID Connect is not supported by your authorization server, one option is to create your own OAuth2 client middleware. You can take a look at the last part of this SO answer for more information: Registering Web API 2 external logins from multiple API clients with OWIN Identity
TejSoft
Updated on July 05, 2022Comments
-
TejSoft almost 2 years
We have developed a set of Web APIs (REST) which are protected by an Authorization server. The Authorization server has issued the client id and client secret. These can be used to obtain an access token. A valid token can be used on subsequent calls to resource servers (REST APIs).
I want to write an web based (Asp.net MVC 5) client that will consume the APIs. Is there a nuget package I can download that will help me to implement the client OAuth2 flow? Can anyone direct me to a good example on client implementation of OAuth2 flow (written in asp.net MVC)?
Update I was able to get access token using the code block below, but what I want is a "client credentials" oauth 2 flow where I don't have to enter login and passwords. The code I have now is:
public class Startup { public void Configuration(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType("ClientCookie"); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationMode = AuthenticationMode.Active, AuthenticationType = "ClientCookie", CookieName = CookieAuthenticationDefaults.CookiePrefix + "ClientCookie", ExpireTimeSpan = TimeSpan.FromMinutes(5) }); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { AuthenticationMode = AuthenticationMode.Active, AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType, SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(), ClientId = ConfigurationManager.AppSettings["AuthServer:ClientId"], ClientSecret = ConfigurationManager.AppSettings["AuthServer:ClientSecret"], RedirectUri = ConfigurationManager.AppSettings["AuthServer:RedirectUrl"], Configuration = new OpenIdConnectConfiguration { AuthorizationEndpoint = "https://identityserver.com/oauth2/authorize", TokenEndpoint = "https://identityserver.com/oauth2/token" }, //ResponseType = "client_credentials", // Doesn't work ResponseType = "token", Notifications = new OpenIdConnectAuthenticationNotifications { AuthenticationFailed = notification => { if (string.Equals(notification.ProtocolMessage.Error, "access_denied", StringComparison.Ordinal)) { notification.HandleResponse(); notification.Response.Redirect("/"); } return Task.FromResult<object>(null); }, AuthorizationCodeReceived = async notification => { using (var client = new HttpClient()) { //var configuration = await notification.Options.ConfigurationManager.GetConfigurationAsync(notification.Request.CallCancelled); String tokenEndPoint = "https://identityserver.com/oauth2/token"; //var request = new HttpRequestMessage(HttpMethod.Post, configuration.TokenEndpoint); var request = new HttpRequestMessage(HttpMethod.Post, tokenEndPoint); request.Content = new FormUrlEncodedContent(new Dictionary<string, string> { { OpenIdConnectParameterNames.ClientId, notification.Options.ClientId }, { OpenIdConnectParameterNames.ClientSecret, notification.Options.ClientSecret }, { OpenIdConnectParameterNames.Code, notification.ProtocolMessage.Code }, { OpenIdConnectParameterNames.GrantType, "authorization_code" }, { OpenIdConnectParameterNames.RedirectUri, notification.Options.RedirectUri } }); var response = await client.SendAsync(request, notification.Request.CallCancelled); response.EnsureSuccessStatusCode(); var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); // Add the access token to the returned ClaimsIdentity to make it easier to retrieve. notification.AuthenticationTicket.Identity.AddClaim(new Claim( type: OpenIdConnectParameterNames.AccessToken, value: payload.Value<string>(OpenIdConnectParameterNames.AccessToken))); } } } }); } }