ASP.NET Core And API access
Welcome to Quickstart 3 for Duende IdentityServer!
The previous quickstarts introduced API access and user authentication. This quickstart will bring the two together.
In addition to the written steps below a YouTube video is available:
OpenID Connect and OAuth combine elegantly; you can achieve both user authentication and api access in a single exchange with the token service.
In Quickstart 2, the token request in the login process asked for only identity resources, that is, only scopes such as profile and openid. In this quickstart, you will add scopes for API resources to that request. IdentityServer will respond with two tokens:
- the identity token, containing information about the authentication process and session, and
- the access token, allowing access to APIs on behalf of the logged on user
Modifying The Client Configuration
Section titled “Modifying The Client Configuration”The client configuration in IdentityServer requires one straightforward update. We should add the api1 resource to the allowed scopes list so that the client will have permission to access it.
Update the Client in src/IdentityServer/Config.cs as follows:
new Client{ ClientId = "web", ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
// where to redirect to after login RedirectUris = { "https://localhost:5002/signin-oidc" },
// where to redirect to after logout PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },
AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "verification", "api1" }}
Modifying The Web client
Section titled “Modifying The Web client”Now configure the client to ask for access to api1 by requesting the api1 scope. This is done in the OpenID Connect handler configuration in src/WebClient/Program.cs:
builder.Services.AddAuthentication(options =>{ options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc";}) .AddCookie("Cookies") .AddOpenIdConnect("oidc", options => { options.Authority = "https://localhost:5001";
options.ClientId = "web"; options.ClientSecret = "secret"; options.ResponseType = "code";
options.Scope.Clear(); options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("api1"); options.Scope.Add("verification"); options.ClaimActions.MapJsonKey("email_verified", "email_verified"); options.GetClaimsFromUserInfoEndpoint = true;
options.MapInboundClaims = false; // Don't rename claim types
options.SaveTokens = true; });
Since SaveTokens is enabled, ASP.NET Core will automatically store the id and access tokens in the properties of the authentication cookie. If you run the solution and authenticate, you will see the tokens on the page that displays the cookie claims and properties created in quickstart 2.
Using The Access Token
Section titled “Using The Access Token”Now you will use the access token to authorize requests from the WebClient to the Api.
Create a page that will
- Retrieve the access token from the session using the GetTokenAsync method from Microsoft.AspNetCore.Authentication
- Set the token in an Authentication: Bearer HTTP header
- Make an HTTP request to the API
- Display the results
Create the Page by running the following command from the src/WebClient/Pages directory:
dotnet new page -n CallApi
Update src/WebClient/Pages/CallApi.cshtml.cs as follows:
public class CallApiModel : PageModel{ public string Json = string.Empty;
public async Task OnGet() { var accessToken = await HttpContext.GetTokenAsync("access_token"); var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var content = await client.GetStringAsync("https://localhost:6001/identity");
var parsed = JsonDocument.Parse(content); var formatted = JsonSerializer.Serialize(parsed, new JsonSerializerOptions { WriteIndented = true });
Json = formatted; }}
And update src/WebClient/Pages/CallApi.cshtml as follows:
@page @model MyApp.Namespace.CallApiModel
<pre>@Model.Json</pre>
Also add a link to the new page in src/WebClient/Shared/_Layout.cshtml with the following:
<li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-page="/CallApi">CallApi</a></li>
Make sure the IdentityServer and Api projects are running, start the WebClient and request /CallApi after authentication.