I have a Blazor server side app that calls an authentication server. I own the auth server (also an ASP.NET Core WebApp) and it is based on OpenIdDict. I can successfully generate an authorization code as I have tested it with oidcdebugger.com.
The auth server redirects back to the app so that app can complete the authorization code flow and the user can access the app.
The first thing I did was the following in MainLayout.razor
:
@inherits LayoutComponentBase
<AuthorizeView>
<NotAuthorized>
<GetAuthorizationCode/>
</NotAuthorized>
<Authorized>
<Header/>
<NavMenu/>
</Authorized>
</AuthorizeView>
@code {
}
GetAuthorizationCode
is a simple component which is:
public class GetAuthorizationCode: ComponentBase
{
[Inject]
protected IAuthService AuthService { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
AuthService.GetAuthorizationCode();
}
}
And the service prepares the request to be sent to the auth server:
public void GetAuthorizationCode()
{
var url = "urltoauthserver";
var parameters = new Dictionary<string, string>()
{
{ "client_id", "hereclientid" },
{ "redirect_uri", "hereredirecturi" },
{ "scope", "openid email profile" },
{ "response_type", "code" },
{ "response_mode", "form_post" },
{ "state", Guid.NewGuid().ToString() },
{ "nonce", "herenonce" }
};
url = QueryHelpers.AddQueryString(url, parameters);
navigationManager.NavigateTo(url);
}
The redirect uri is an api controller within the Blazor app itself (not an another external api). I need to use an api controller because the redirect uri is a POST and looks like this:
[Route("api/[controller]")]
[ApiController]
[AllowAnonymous]
public class LoginController : ControllerBase
{
[HttpPost]
public IActionResult Callback([FromForm] string code, [FromForm] string state)
{
return Ok($"Login callback. Access token: {code}");
}
}
The flow should be that once the auth server authenticates the user and the authorization code is sent back to the redirect uri, the action above should create a request with the authorizatoin code to send to the auth server and receive an access token.
In startup.cs
I also configured OpenIdConnect as follows:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.ClientId = "hereclientid";
options.ClientSecret = "hereclientsecret";
options.RequireHttpsMetadata = false;
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.ResponseType = OpenIdConnectResponseType.Code;
options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
options.Authority = "authserver";
options.Scope.Add("email");
options.Scope.Add("profile");
options.SecurityTokenValidator = new JwtSecurityTokenHandler
{
InboundClaimTypeMap = new Dictionary<string, string>()
};
options.TokenValidationParameters.NameClaimType = "name";
});
The problem is that the action is never reached because during redirection the GetAuthorizationCode
is called over and over again.
EDIT The endless loop occurs if the redirect is a GET. If the redirect is a POST, I get a 400 Bad Request and this is the log:
2021-02-04 16:56:19.628 +01:00 [INF] Request starting HTTP/2 POST https://localhost:44379/api/Login/Callback application/x-www-form-urlencoded 91 2021-02-04 16:56:19.628 +01:00 [INF] CORS policy execution successful. 2021-02-04 16:56:19.629 +01:00 [INF] Executing endpoint '/_Host' 2021-02-04 16:56:19.629 +01:00 [INF] Route matched with {page = "/_Host", action = "", controller = ""}. Executing page /_Host 2021-02-04 16:56:19.639 +01:00 [INF] Antiforgery token validation failed. The required antiforgery request token was not provided in either form field "__RequestVerificationToken" or header value "RequestVerificationToken". Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The required antiforgery request token was not provided in either form field "__RequestVerificationToken" or header value "RequestVerificationToken". at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext) at Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.ValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context) 2021-02-04 16:56:19.671 +01:00 [INF] Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.AutoValidateAntiforgeryTokenAuthorizationFilter'. 2021-02-04 16:56:19.674 +01:00 [INF] Executing HttpStatusCodeResult, setting HTTP status code 400 2021-02-04 16:56:19.674 +01:00 [INF] Executed page /_Host in 45.2108ms 2021-02-04 16:56:19.674 +01:00 [INF] Executed endpoint '/_Host' 2021-02-04 16:56:19.675 +01:00 [INF] Request finished HTTP/2 POST https://localhost:44379/api/Login/Callback application/x-www-form-urlencoded 91 - 400 - - 47.2169ms
I added [IgnoreAntiForgeryToken]
for the POST action but it doesn't work