protected override async Task <bool> HandleUnauthorizedAsync(ChallengeContext context)
{
var properties = new AuthenticationProperties(context.Properties);
if (Options.Endpoint == null)
{
// Note: altering options during a request is not thread safe but
// would only result in multiple discovery requests in the worst case.
Options.Endpoint = await DiscoverEndpointAsync(Options.Authority);
}
if (Options.Endpoint == null)
{
Logger.LogError("The user agent cannot be redirected to the identity provider because no " +
"endpoint was registered in the options or discovered through Yadis.");
return(true);
}
// Determine the realm using the current address
// if one has not been explicitly provided;
var realm = Options.Realm;
if (string.IsNullOrEmpty(realm))
{
realm = Request.Scheme + "://" + Request.Host + OriginalPathBase;
}
// Use the current address as the final location where the user agent
// will be redirected to if one has not been explicitly provided.
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = Request.Scheme + "://" + Request.Host +
OriginalPathBase + Request.Path + Request.QueryString;
}
// Store the return_to parameter for later comparison.
properties.Items[OpenIdAuthenticationConstants.Properties.ReturnTo] =
Request.Scheme + "://" + Request.Host +
OriginalPathBase + Options.CallbackPath;
// Generate a new anti-forgery token.
GenerateCorrelationId(properties);
var state = UrlEncoder.Encode(Options.StateDataFormat.Protect(properties));
// Create a new message containing the OpenID 2.0 request parameters.
// See http://openid.net/specs/openid-authentication-2_0.html#requesting_authentication
var message = new OpenIdAuthenticationMessage {
ClaimedIdentifier = "http://specs.openid.net/auth/2.0/identifier_select",
Identity = "http://specs.openid.net/auth/2.0/identifier_select",
Mode = OpenIdAuthenticationConstants.Modes.CheckIdSetup,
Namespace = OpenIdAuthenticationConstants.Namespaces.OpenId,
Realm = realm,
ReturnTo = QueryHelpers.AddQueryString(
uri: properties.Items[OpenIdAuthenticationConstants.Properties.ReturnTo],
name: OpenIdAuthenticationConstants.Parameters.State, value: state)
};
if (Options.Attributes.Count != 0)
{
// openid.ns.ax (http://openid.net/srv/ax/1.0)
message.SetParameter(
prefix: OpenIdAuthenticationConstants.Prefixes.Namespace,
name: OpenIdAuthenticationConstants.Aliases.Ax,
value: OpenIdAuthenticationConstants.Namespaces.Ax);
// openid.ax.mode (fetch_request)
message.SetParameter(
prefix: OpenIdAuthenticationConstants.Prefixes.Ax,
name: OpenIdAuthenticationConstants.Parameters.Mode,
value: OpenIdAuthenticationConstants.Modes.FetchRequest);
foreach (var attribute in Options.Attributes)
{
message.SetParameter(
prefix: OpenIdAuthenticationConstants.Prefixes.Ax,
name: $"{OpenIdAuthenticationConstants.Prefixes.Type}.{attribute.Key}",
value: attribute.Value);
}
// openid.ax.required
message.SetParameter(
prefix: OpenIdAuthenticationConstants.Prefixes.Ax,
name: OpenIdAuthenticationConstants.Parameters.Required,
value: string.Join(",", Options.Attributes.Select(attribute => attribute.Key)));
}
Response.Redirect(await GenerateChallengeUrlAsync(message));
return(true);
}