I'm trying to implement OpenID Connect with Azure AD in a .NET Core 3.0 ASP.NET Core API service.
It is an API service only, with no UI, and a separate SPA is used to access the API service.
Per the instructions here, I'm sending the sign-in request from my SPA, which, after authentication is being redirected back to the /signin-oidc endpoint on my API.
At this point, I get an error:-
Error from RemoteAuthentication: "Unable to unprotect the message.State.".
The initial request from the SPA looks like this:-
tenantId = my Azure AD tenant ID
clientId = my Azure AD application ID
responseType = "id_token"
redirectUri = "http://localhost:12345/signin-oidc"
scope = "openid"
responseMode = "form_post"
state = "12345"
nonce = "67890"
https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize?client_id={clientId}&response_type={responseType}&redirect_uri={redirectUri}&scope={scope}&response_mode={responseMode}&state={state}&nonce={nonce}
And my API startup code looks like this:-
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureAD(o =>
{
o.ClientId = "(tenant id)";
o.TenantId = "(client id)";
o.Instance = "https://login.microsoftonline.com/";
})
.AddAzureADBearer(o =>
{
o.ClientId = "(tenant id)";
o.TenantId = "(client id)";
o.Instance = "https://login.microsoftonline.com/";
});
If I omit the state parameter from the initial request, I get a different error:-
Error from RemoteAuthentication: "OpenIdConnectAuthenticationHandler: message.State is null or empty.".
The referenced instructions say that state is recommended, not required:-
A value included in the request that also will be returned in the token response. It can be a string of any content you want. A randomly generated unique value typically is used to prevent cross-site request forgery attacks. The state also is used to encode information about the user's state in the app before the authentication request occurred, such as the page or view the user was on.
However, the errors I'm getting seem to imply that state is required, and needs to be specially generated.
I've also tried with the following startup code, and get the same errors:-
services.AddAuthentication(options =>
{
options.DefaultScheme = Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.ClientId = "(client id)";
options.Authority = "https://login.microsoftonline.com/" + "(tenant id)";
});