|
|
@ -35,6 +35,7 @@ namespace Mvc.Server { |
|
|
_userManager = userManager; |
|
|
_userManager = userManager; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#region Authorization code, implicit and implicit flows
|
|
|
// Note: to support interactive flows like the code flow,
|
|
|
// Note: to support interactive flows like the code flow,
|
|
|
// you must provide your own authorization endpoint action:
|
|
|
// you must provide your own authorization endpoint action:
|
|
|
|
|
|
|
|
|
@ -108,7 +109,9 @@ namespace Mvc.Server { |
|
|
// to the post_logout_redirect_uri specified by the client application.
|
|
|
// to the post_logout_redirect_uri specified by the client application.
|
|
|
return SignOut(OpenIdConnectServerDefaults.AuthenticationScheme); |
|
|
return SignOut(OpenIdConnectServerDefaults.AuthenticationScheme); |
|
|
} |
|
|
} |
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Password and refresh token flows
|
|
|
// Note: to support non-interactive flows like password,
|
|
|
// Note: to support non-interactive flows like password,
|
|
|
// you must provide your own token endpoint action:
|
|
|
// you must provide your own token endpoint action:
|
|
|
|
|
|
|
|
|
@ -169,13 +172,45 @@ namespace Mvc.Server { |
|
|
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme); |
|
|
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
else if (request.IsRefreshTokenGrantType()) { |
|
|
|
|
|
// Retrieve the claims principal stored in the refresh token.
|
|
|
|
|
|
var info = await HttpContext.Authentication.GetAuthenticateInfoAsync( |
|
|
|
|
|
OpenIdConnectServerDefaults.AuthenticationScheme); |
|
|
|
|
|
|
|
|
|
|
|
// Retrieve the user profile corresponding to the refresh token.
|
|
|
|
|
|
var user = await _userManager.GetUserAsync(info.Principal); |
|
|
|
|
|
if (user == null) { |
|
|
|
|
|
return BadRequest(new OpenIdConnectResponse { |
|
|
|
|
|
Error = OpenIdConnectConstants.Errors.InvalidGrant, |
|
|
|
|
|
ErrorDescription = "The refresh token is no longer valid." |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Ensure the user is still allowed to sign in.
|
|
|
|
|
|
if (!await _signInManager.CanSignInAsync(user)) { |
|
|
|
|
|
return BadRequest(new OpenIdConnectResponse { |
|
|
|
|
|
Error = OpenIdConnectConstants.Errors.InvalidGrant, |
|
|
|
|
|
ErrorDescription = "The user is no longer allowed to sign in." |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Create a new authentication ticket, but reuse the properties stored
|
|
|
|
|
|
// in the refresh token, including the scopes originally granted.
|
|
|
|
|
|
var ticket = await CreateTicketAsync(request, user, info.Properties); |
|
|
|
|
|
|
|
|
|
|
|
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return BadRequest(new OpenIdConnectResponse { |
|
|
return BadRequest(new OpenIdConnectResponse { |
|
|
Error = OpenIdConnectConstants.Errors.UnsupportedGrantType, |
|
|
Error = OpenIdConnectConstants.Errors.UnsupportedGrantType, |
|
|
ErrorDescription = "The specified grant type is not supported." |
|
|
ErrorDescription = "The specified grant type is not supported." |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
private async Task<AuthenticationTicket> CreateTicketAsync(OpenIdConnectRequest request, ApplicationUser user) { |
|
|
private async Task<AuthenticationTicket> CreateTicketAsync( |
|
|
|
|
|
OpenIdConnectRequest request, ApplicationUser user, |
|
|
|
|
|
AuthenticationProperties properties = null) { |
|
|
// Create a new ClaimsPrincipal containing the claims that
|
|
|
// Create a new ClaimsPrincipal containing the claims that
|
|
|
// will be used to create an id_token, a token or a code.
|
|
|
// will be used to create an id_token, a token or a code.
|
|
|
var principal = await _signInManager.CreateUserPrincipalAsync(user); |
|
|
var principal = await _signInManager.CreateUserPrincipalAsync(user); |
|
|
@ -193,20 +228,21 @@ namespace Mvc.Server { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Create a new authentication ticket holding the user identity.
|
|
|
// Create a new authentication ticket holding the user identity.
|
|
|
var ticket = new AuthenticationTicket( |
|
|
var ticket = new AuthenticationTicket(principal, properties, |
|
|
principal, new AuthenticationProperties(), |
|
|
|
|
|
OpenIdConnectServerDefaults.AuthenticationScheme); |
|
|
OpenIdConnectServerDefaults.AuthenticationScheme); |
|
|
|
|
|
|
|
|
// Set the list of scopes granted to the client application.
|
|
|
if (!request.IsRefreshTokenGrantType()) { |
|
|
// Note: the offline_access scope must be granted
|
|
|
// Set the list of scopes granted to the client application.
|
|
|
// to allow OpenIddict to return a refresh token.
|
|
|
// Note: the offline_access scope must be granted
|
|
|
ticket.SetScopes(new[] { |
|
|
// to allow OpenIddict to return a refresh token.
|
|
|
OpenIdConnectConstants.Scopes.OpenId, |
|
|
ticket.SetScopes(new[] { |
|
|
OpenIdConnectConstants.Scopes.Email, |
|
|
OpenIdConnectConstants.Scopes.OpenId, |
|
|
OpenIdConnectConstants.Scopes.Profile, |
|
|
OpenIdConnectConstants.Scopes.Email, |
|
|
OpenIdConnectConstants.Scopes.OfflineAccess, |
|
|
OpenIdConnectConstants.Scopes.Profile, |
|
|
OpenIddictConstants.Scopes.Roles |
|
|
OpenIdConnectConstants.Scopes.OfflineAccess, |
|
|
}.Intersect(request.GetScopes())); |
|
|
OpenIddictConstants.Scopes.Roles |
|
|
|
|
|
}.Intersect(request.GetScopes())); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return ticket; |
|
|
return ticket; |
|
|
} |
|
|
} |
|
|
|