/// <summary> /// Serialize and sign the authentication ticket. /// </summary> /// <returns>The serialized and signed ticket.</returns> public Task <string> SerializeTicketAsync() { if (SecurityTokenHandler == null) { return(Task.FromResult <string>(null)); } // Work around a bug introduced in System.IdentityModel.Tokens for ASP.NET 5. // See https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/133 var identity = (ClaimsIdentity)AuthenticationTicket.Principal.Identity; for (var actor = identity.Actor; actor != null; actor = actor.Actor) { actor.BootstrapContext = new JwtSecurityToken(claims: actor.Claims); } // When creating an identity token intended for a single audience, it's usually better // to format the "aud" claim as a string, but CreateToken doesn't support multiple audiences: // to work around this limitation, audience is initialized with a single resource and // JwtPayload.Aud is replaced with an array containing the multiple resources if necessary. // See http://openid.net/specs/openid-connect-core-1_0.html#IDToken var token = SecurityTokenHandler.CreateToken( subject: identity, issuer: Issuer, audience: Audiences.ElementAtOrDefault(0), signatureProvider: SignatureProvider, signingCredentials: SigningCredentials, notBefore: AuthenticationTicket.Properties.IssuedUtc.Value.UtcDateTime, expires: AuthenticationTicket.Properties.ExpiresUtc.Value.UtcDateTime); if (Audiences.Count() > 1) { token.Payload[JwtRegisteredClaimNames.Aud] = Audiences.ToArray(); } return(Task.FromResult(SecurityTokenHandler.WriteToken(token))); }