Browse Source

Move the profile/email scopes check to OpenIddictProvider.ValidateAuthorizationRequest

pull/60/head
Kévin Chalet 10 years ago
parent
commit
111a34a4af
  1. 52
      src/OpenIddict.Core/OpenIddictProvider.Authentication.cs
  2. 37
      src/OpenIddict.Mvc/OpenIddictController.cs

52
src/OpenIddict.Core/OpenIddictProvider.Authentication.cs

@ -63,6 +63,34 @@ namespace OpenIddict {
return;
}
// If the user is connected, ensure that a corresponding profile exists and that
// the appropriate set of scopes is requested to prevent personal data leakage.
if (context.HttpContext.User.Identities.Any(identity => identity.IsAuthenticated)) {
// Ensure the user profile still exists in the database.
var user = await manager.FindByIdAsync(context.HttpContext.User.GetUserId());
if (user == null) {
context.Reject(
error: OpenIdConnectConstants.Errors.ServerError,
description: "An internal error has occurred.");
return;
}
// Return an error if the username corresponds to the registered
// email address and if the "email" scope has not been requested.
if (context.Request.HasScope(OpenIdConnectConstants.Scopes.Profile) &&
!context.Request.HasScope(OpenIdConnectConstants.Scopes.Email) &&
string.Equals(await manager.GetUserNameAsync(user),
await manager.GetEmailAsync(user),
StringComparison.OrdinalIgnoreCase)) {
context.Reject(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The 'email' scope is required.");
return;
}
}
// Run additional checks for prompt=none requests.
if (string.Equals(context.Request.Prompt, "none", StringComparison.Ordinal)) {
// If the user is not authenticated, return an error to the client application.
@ -96,30 +124,6 @@ namespace OpenIddict {
return;
}
// Ensure the user profile still exists in the database.
var user = await manager.FindByIdAsync(principal.GetUserId());
if (user == null) {
context.Reject(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The id_token_hint parameter is invalid.");
return;
}
// Return an error if the username corresponds to the registered
// email address and if the "email" scope has not been requested.
if (context.Request.HasScope(OpenIdConnectConstants.Scopes.Profile) &&
!context.Request.HasScope(OpenIdConnectConstants.Scopes.Email) &&
string.Equals(await manager.GetUserNameAsync(user),
await manager.GetEmailAsync(user),
StringComparison.OrdinalIgnoreCase)) {
context.Reject(
error: OpenIdConnectConstants.Errors.InvalidRequest,
description: "The 'email' scope is required.");
return;
}
}
context.Validate();

37
src/OpenIddict.Mvc/OpenIddictController.cs

@ -96,6 +96,18 @@ namespace OpenIddict.Mvc {
[Authorize, HttpPost, ValidateAntiForgeryToken]
public virtual async Task<IActionResult> Accept() {
// Note: when a fatal error occurs during the request processing, an OpenID Connect response
// is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler.
// In this case, the OpenID Connect request is null and cannot be used.
// When the user agent can be safely redirected to the client application,
// OpenIdConnectServerHandler automatically handles the error and MVC is not invoked.
// You can safely remove this part and let AspNet.Security.OpenIdConnect.Server automatically
// handle the unrecoverable errors by switching ApplicationCanDisplayErrors to false.
var response = HttpContext.GetOpenIdConnectResponse();
if (response != null) {
return View("Error", response);
}
// Extract the authorization request from the cache,
// the query string or the request form.
var request = HttpContext.GetOpenIdConnectRequest();
@ -115,19 +127,6 @@ namespace OpenIddict.Mvc {
});
}
// Return an error if the username corresponds to the registered
// email address and if the "email" scope has not been requested.
if (request.HasScope(OpenIdConnectConstants.Scopes.Profile) &&
!request.HasScope(OpenIdConnectConstants.Scopes.Email) &&
string.Equals(await Manager.GetUserNameAsync(user),
await Manager.GetEmailAsync(user),
StringComparison.OrdinalIgnoreCase)) {
return View("Error", new OpenIdConnectMessage {
Error = OpenIdConnectConstants.Errors.InvalidRequest,
ErrorDescription = "The 'email' scope is required."
});
}
// Create a new ClaimsIdentity containing the claims that
// will be used to create an id_token, a token or a code.
var identity = await Manager.CreateIdentityAsync(user, request.GetScopes());
@ -172,6 +171,18 @@ namespace OpenIddict.Mvc {
[Authorize, HttpPost, ValidateAntiForgeryToken]
public virtual IActionResult Deny() {
// Note: when a fatal error occurs during the request processing, an OpenID Connect response
// is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler.
// In this case, the OpenID Connect request is null and cannot be used.
// When the user agent can be safely redirected to the client application,
// OpenIdConnectServerHandler automatically handles the error and MVC is not invoked.
// You can safely remove this part and let AspNet.Security.OpenIdConnect.Server automatically
// handle the unrecoverable errors by switching ApplicationCanDisplayErrors to false.
var response = HttpContext.GetOpenIdConnectResponse();
if (response != null) {
return View("Error", response);
}
// Extract the authorization request from the cache,
// the query string or the request form.
var request = HttpContext.GetOpenIdConnectRequest();

Loading…
Cancel
Save