Closed nielsedens closed 1 year ago
These OAuthAuthorizationServer components are outdated and we do not recommend using them anymore. There are better community implementations available like IdentityServer, or you can use a hosted solution like Azure Active Directory.
Thank you for your response @Tratcher.
Replacing the OAuthAuthorizationServer components at this point is not really a cost effective solution. Beside the work, a component like IdentityServer is also no longer maintained as open source / free software. Maybe OpenIddict will be a candidate when updating our software to .NET 6.0.
For now I have found a workaround using the IOwinResponse.OnSendingHeaders
.
public override Task AuthorizationEndpointResponse(OAuthAuthorizationEndpointResponseContext context)
{
Uri _uri = new Uri(context.AuthorizeEndpointRequest.RedirectUri);
NameValueCollection _returnParams = HttpUtility.ParseQueryString(_uri.Query);
foreach (KeyValuePair<string, object> _parameter in context.AdditionalResponseParameters)
{
_returnParams[_parameter.Key] = _parameter.Value.ToString();
}
_returnParams[IdentityProviderConstants.Parameters.Code] = context.AuthorizationCode;
if (!string.IsNullOrEmpty(context.AuthorizeEndpointRequest.State))
{
_returnParams[IdentityProviderConstants.Parameters.State] = context.AuthorizeEndpointRequest.State;
}
// If 'response_mode=form_post' was send, handle returning the appropriate response here; see
// https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html. We need to handle it here,
// because the caller of this method (`OAuthAuthorizationServerHandler.ApplyResponseGrantAsync`)
// will issue a redirect to `context.Options.FormPostEndpoint`, which we want to prevent. For
// other response modes let the caller handle the response.
if (context.AuthorizeEndpointRequest.IsFormPostResponseMode)
{
StringBuilder _inputFields = new StringBuilder();
foreach (string _returnParam in _returnParams.AllKeys)
{
foreach (string _value in _returnParams.GetValues(_returnParam) ?? Array.Empty<string>())
{
_inputFields.AppendLine($@"<input type=""hidden"" name=""{_returnParam}"" value=""{_value}""/>");
}
}
StringBuilder _responseBody = new StringBuilder(
$@"
<html>
<head><title>Submit This Form</title></head>
<body onload=""javascript:document.forms[0].submit()"">
<form method=""post"" action=""{context.AuthorizeEndpointRequest.RedirectUri}"">
{_inputFields.ToString().TrimEnd()}
</form>
</body>
</html>");
context.Response.Write(_responseBody.ToString());
context.Response.OnSendingHeaders(
state =>
{
if (state is OAuthAuthorizationEndpointResponseContext _context)
{
// Undo the 'redirect' set by the caller of `AuthorizationEndpointResponse`, i.e.
// `OAuthAuthorizationServerHandler.ApplyResponseGrantAsync`.
_context.Response.StatusCode = 200;
_context.Response.Headers.Remove("Location");
}
},
context);
context.RequestCompleted();
}
return Task.CompletedTask;
}
Maybe OpenIddict will be a candidate when updating our software to .NET 6.0.
It's worth noting OpenIddict is now natively compatible with Microsoft.Owin
(support was added in 3.0 to allow OAuthAuthorizationServerMiddleware
and OpenIdConnectServerMiddleware
users to modernize their OAuth 2.0/OIDC implementation without being forced to migrate to ASP.NET Core).
Hello,
I'm trying to implement the OAuth authorize endpoint including support for the
response_type=form_post
.By default the
OAuthAuthorizationServerHandler.ApplyResponseGrantAsync
method sends a redirect HTTP response, with a redirect location that is the configuredOAuthAuthorizationServerOptions.FormPostEndpoint
. According to https://docs.microsoft.com/en-us/previous-versions/aspnet/mt180788(v=vs.113) this endpoint is responsible to send the HTML to the client/browser that will post back the authorize response data (i.e. the authorization code or access code, depending on the flow, plus additional data; https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html). TheOAuthAuthorizationServerHandler.ApplyResponseGrantAsync
method sends this redirect just after calling theIOAuthAuthorizationServerProvider.AuthorizationEndpointResponse
.Why is the
OAuthAuthorizationServerHandler.ApplyResponseGrantAsync
sending this redirect, instead of sending a form post response immediately?I would like to prevent this redirect to the
FormPostEndPoint
and send the form post HTML immediately to the client/browserIOAuthAuthorizationServerProvider.AuthorizationEndpointResponse
. I can write the required HTML body toOAuthAuthorizationEndpointResponseContext.Response
, but the redirect is still happening. Calling thecontext.RequestCompleted()
does not help, becauseOAuthAuthorizationServerHandler.ApplyResponseGrantAsync
ignores this. The redirect response sent to the client does contain the body, but is still a 302 response including a location header, rather than a 200 response.My implementation of
AuthorizationEndpointResponse
is currentlyAny feedback is appreciated.