Web App Profile - ob1dev/Auth0 GitHub Wiki
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_token
itself. 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
.
You have now completed the integrating Auth0 with Web App. You have learned how to add additional scopes, such as profile
and email
to including more user's related data into the ID Token, as well as how to read claims from the token. In the next tutorial you'll expand the functionality by adding Auth0 API in addition to Auth Application.