-
Notifications
You must be signed in to change notification settings - Fork 1
Web App Profile
Okay, at this point the Web App can sing in and sign out a user. The next step is to add some details about authenticated user.
Previously the Web App asked Auth0 for the scope openid only. As a result, it got the token id_token with information to use the OpenID Connect protocol to verify the identity of a user. To be more specific, if the scope is set to openid, then the token id_token will contain the following claims:
{
"iss": "Issuer Identifier for the Issuer of the response.",
"sub": "Subject Identifier.",
"aud": "Audience(s) that this ID Token is intended for.",
"exp": "Expiration time on or after which the ID Token MUST NOT be accepted for processing.",
"iat": "Time at which the JWT was issued."
}NOTE
For more information about ID Token, see its specification here.
IMPORTANT
The Auth0 doesn't return a naked token. It wraps a token into a digitally signed self-container aka JSON Web Token format (JWT). Such token can't be easily read or modified by 3rd parties, because it needs to be decoded/encoded using a trusted certificate. You can read more about JWT here, as well as decode a token.
NOTE
For more information about Auth0 ID Token wrapped into JWT, read here.
Now we need the Web App to ask for additional scopes such as profile and email. As a result, the token id_token will contain the following claims in addition to the iss, sub, aud, exp and iat ones.
Scope profile:
{
"name": "End-User's full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User's locale and preferences.",
"family_name": "Surname(s) or last name(s) of the End-User.",
"given_name": "Given name(s) or first name(s) of the End-User.",
"middle_name": "Middle name(s) of the End-User.",
"nickname": "Casual name of the End-User that may or may not be the same as the given_name.",
"preferred_username": "Shorthand name by which the End-User wishes to be referred to at the RP.",
"profile": "URL of the End-User's profile page.",
"picture": "Note that this URL SHOULD specifically reference a profile photo of the End-User suitable for displaying when describing the End-User, rather than an arbitrary photo taken by the End-User.",
"website": "URL of the End-User's Web page or blog.",
"gender": "End-User's gender.",
"birthdate": "End-User's birthday, represented as an ISO 8601:2004 [ISO8601‑2004] YYYY-MM-DD format.",
"zoneinfo": "String from zoneinfo zoneinfo time zone database representing the End-User's time zone.",
"locale": "End-User's locale, represented as a BCP47 RFC5646 language tag.",
"updated_at": "Time the End-User's information was last updated."
}Scope email:
{
"email": "End-User's preferred e-mail address.",
"email_verified": "True if the End-User's e-mail address has been verified; otherwise false."
}In the file Startup.cs, modify the method ConfigureServices as shown below.
public void ConfigureServices(IServiceCollection services)
{
...
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
...
}Additionally, I want the property User.Identity.Name returns whatever values has the claim nickmame in the returned token id_token. To make it that way, modify the method ConfigureServices with those lines.
public void ConfigureServices(IServiceCollection services)
{
...
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "nickname",
};
...
}Modify partial view _LoginPartial under the folder Views\Shared, to render a user's name and picture, as well as a link to profile page, which you will add a bit later.
...
@using System.Security.Principal
@if (User.Identity.IsAuthenticated)
{
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a class="dropdown-toggle" role="button" aria-expanded="false" aria-haspopup="true" href="#" data-toggle="dropdown">
<img width="20" height="20" class="avatar" alt="@User.Identity.Name" src="@User.Claims.FirstOrDefault(c => c.Type == "picture")?.Value">
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li class="dropdown-header header-nav-current-user">Signed in as <strong>@User.Identity.Name</strong></li>
<li class="dropdown-divider" role="separator"></li>
<li><a asp-controller="Account" asp-action="Profile">Your profile</a></li>
<li><a asp-controller="Account" asp-action="Signout">Sign out</a></li>
</ul>
</li>
</ul>
}
else
{
...
}Create a new class UserProfileModel under the folder Models as shown below.
public class UserProfileModel
{
public string EmailAddress { get; set; }
public string Name { get; set; }
public string ProfileImage { get; set; }
public string IdToken { get; set; }
}Create a new view Profile under the folder Views\Account, to render a user's profile.
@model OneGit.Web.Models.UserProfileModel
@{
ViewData["Title"] = "Profile";
}
<h2>@ViewData["Title"]</h2>
<img class="img-rounded img-responsive" alt="@Model.Name" src="@Model.ProfileImage" />
<h3>@Model.Name</h3>
<p>
<i class="glyphicon glyphicon-envelope"></i> <code>@Model.EmailAddress</code>
</p>
<p>
<i class="glyphicon glyphicon-user"></i> <code>id_token</code>
<div>
<mark>@Model.IdToken</mark>
</div>
</p>Modify the class AccountController under the folder Controllers, by adding a new action Profile.
[Route("[controller]/[action]")]
public class AccountController : Controller
{
...
[HttpGet]
public async Task<IActionResult> Profile()
{
return View(new UserProfileModel()
{
Name = User.Identity.Name,
EmailAddress = User.Claims.FirstOrDefault(c => c.Type == "name")?.Value,
ProfileImage = User.Claims.FirstOrDefault(c => c.Type == "picture")?.Value,
IdToken = await HttpContext.GetTokenAsync("id_token")
});
}
}IMPORTANT
As you can see, the model is populated using claims, as well as the value of theid_tokenitself. The reason why I want to render the token, is because I want you to pass its encoded value to https://jwt.io/ and examine the decoded parts - Header (algorithm & token type), Payload (Data) and Verify Signature. If you add or remove scopesprofile,Payload.
Home | Web App | Web API | Auth0 | Auth0 Portal