Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] "The issuer '(null)' is invalid" error when I request my API with bearer token #1167

Closed
1 of 7 tasks
Gtyrande opened this issue Apr 28, 2021 · 17 comments
Closed
1 of 7 tasks
Assignees
Labels
bug Something isn't working css This issue is also a support case or similar to a support case in progress enhancement New feature or request external fixed P1 question Further information is requested

Comments

@Gtyrande
Copy link

Which Version of MSAL are you using ?
msal.net 1.9.0

Platform
asp.net core 5.0

What authentication flow has the issue?

  • Desktop / Mobile
    • Interactive
    • Integrated Windows Auth
    • Username Password
    • Device code flow (browserless)
  • Web App
    • Authorization code
    • OBO
  • Daemon App
    • Service to Service calls

Other? - please describe;

Is this a new or existing app?
This is a new app or experiment

Repro

I have added following lines of code.

// startup.cs
services.AddMicrosoftIdentityWebApiAuthentication(Configuration, "AzureAd");
app.UseAuthentication();

// WeatherForecastController
[Authorize]
[RequiredScope("Default")]

// appsettings.json
"AzureAd": {
    "Instance": "https://login.chinacloudapi.cn/",
    "ClientId": "my client id",
    "Domain": "my organization domain",
    "TenantId": "my organization tenant id",
    "Authority": "https://login.chinacloudapi.cn/my organization tenant id/"
}

Expected behavior
I checked my token on jwt.ms, it shows everything is good.
image

Actual behavior
I use Postman to request the API, and the API tells me issuer is null in my token.
image

@jmprieur
Copy link
Collaborator

I think that this is a Microsoft.Identity.Web issue (in the issuer validation)

###Analysis
Looking at the OIDC metadata for https://login.chinacloudapi.cn, I don't see the aliases property, whereas it's currently required by the standard issuer validator:

.Where(m => m.Aliases.Any(a => string.Equals(a, authorityHost, StringComparison.OrdinalIgnoreCase)))

Metadata:
https://login.chinacloudapi.cn/common/.well-known/openid-configuration

Possible fix:

Union m => m.Aliases with m.Issuer which is defined in the case of https://login.chinacloudapi.cn, and before doing the call to Distinct.

Possible work around

I have not tested. maybe have ValidIssuer set to https://sts.chinacloudapi.cn/{tenantid}/ in the appsettings.json?

@Gtyrande : how urgent is this for you?

@jmprieur jmprieur transferred this issue from AzureAD/microsoft-authentication-library-for-dotnet Apr 29, 2021
@jmprieur jmprieur added bug Something isn't working P1 labels Apr 29, 2021
@bgavrilMS bgavrilMS self-assigned this Apr 29, 2021
@bgavrilMS
Copy link
Member

@Gtyrande can you try with https://login.partner.microsoftonline.cn/ instead?

@bgavrilMS
Copy link
Member

bgavrilMS commented Apr 29, 2021

@jmprieur - the aliases are not in the OIDC metadata, they are in the instance metadata document https://login.microsoftonline.com/common/discovery/instance?authorization_endpoint=https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize&api-version=1.1

The https://login.chinacloudapi.cn/ alias is no longer the preffered network alias, but it's still an alias. However, sts.chinacloud.cn is not an alias. Does this mean this is an external problem?

@Gtyrande
Copy link
Author

@Gtyrande can you try with https://login.partner.microsoftonline.cn/ instead?

I tried sts.chinadloudapi.cn and login.partner.microsoftonline.cn at both frontend acquire token process and backend validate token process, result is same as I posted.

I never use sts.chinacloud.cn before in my code, but in access token the issuer is always sts.chinacloud.cn. Maybe there is something wrong with msal.js 2.0?

@Gtyrande
Copy link
Author

I think that this is a Microsoft.Identity.Web issue (in the issuer validation)

###Analysis
Looking at the OIDC metadata for https://login.chinacloudapi.cn, I don't see the aliases property, whereas it's currently required by the standard issuer validator:

.Where(m => m.Aliases.Any(a => string.Equals(a, authorityHost, StringComparison.OrdinalIgnoreCase)))

Metadata:
https://login.chinacloudapi.cn/common/.well-known/openid-configuration

Possible fix:

Union m => m.Aliases with m.Issuer which is defined in the case of https://login.chinacloudapi.cn, and before doing the call to Distinct.

Possible work around

I have not tested. maybe have ValidIssuer set to https://sts.chinacloudapi.cn/{tenantid}/ in the appsettings.json?

@Gtyrande : how urgent is this for you?

I tried https://sts.chinacloudapi.cn/{tenantid}/ but nothing changed.

I'm just to write a demo for our vendor to explain the process of Azure AD. Their tech-stack is Maven/Java, so it's not an urgent problem if msal.java is good.

I will tell them to try msal.java. If it's not work, they can customize a validator in middleware.

@jmprieur jmprieur added P2 and removed P1 labels Apr 29, 2021
@bgavrilMS bgavrilMS added external and removed P2 bug Something isn't working labels Apr 29, 2021
@bgavrilMS
Copy link
Member

@Gtyrande - this seems to be an actual server bug. The token is marked as having been issued by sts.chinacloud.cn\<tenant>, however this is not cloud alias is not known. AAD publishes the aliases here and the token validator has no way of knowing that https://login.chinacloudapi.cn/ and https://sts.chinacloud.cn/ are the same.

As a possible workaround, you can try to set the authority as sts.chinacloud.cn, but I would advise against it. The course of action is to open an incident (ICM, as I believe you are internal) to the server team (ESTS > ESTS). You'll need a correlation id for when you get a token. Ping us if you need help.

@Gtyrande
Copy link
Author

@bgavrilMS

  1. I tried to set authority as sts.chinacloud.cn but response shows The issuer '(null)' is invalid also. So I prefer to think of it as a problem in msal.net.
  2. Actually I'm not a Microsoft employee. Ha ha.

@jennyf19 jennyf19 assigned jennyf19 and unassigned bgavrilMS May 1, 2021
@jennyf19 jennyf19 added this to the 1.10.0 milestone May 1, 2021
@jennyf19 jennyf19 modified the milestones: 1.10.0, 1.9.2 May 1, 2021
@jennyf19 jennyf19 removed this from the 1.9.2 milestone May 3, 2021
@jmprieur jmprieur added the question Further information is requested label May 10, 2021
@jmprieur jmprieur added the enhancement New feature or request label May 31, 2021
@jennyf19
Copy link
Collaborator

jennyf19 commented Jun 4, 2021

@Gtyrande the fix is in this branch if you want to try it. Someone from US gov cloud has tried it out with success. thank you.

@jennyf19 jennyf19 added css This issue is also a support case or similar to a support case in progress fixed labels Jun 4, 2021
@jmprieur jmprieur added the bug Something isn't working label Jun 7, 2021
@jennyf19
Copy link
Collaborator

Fixed in 1.13 release.

@Gtyrande
Copy link
Author

@jennyf19 Sorry for late reply and thank you for new release. As I tested this error never shows again.

But I got a 404 response and I can’t tell where the problem is. Could you help me about this?
image

My Vue App code:

const msalConfig = {
    auth: {
        clientId: "099dd5c9-f8bd-48a8-abe6-46415677cb02",
        authority: "https://login.partner.microsoftonline.cn/2c3c280f-2394-453f-944d-6df0dd9c338e/",
        redirectUri: "http://localhost:8080/"
    }
};

scopes: ["api://eaaca060-36c7-4f8f-a7a2-0bac9d3d2bdf/.default"]

My .NET API code:

// startup.cs
services.AddMicrosoftIdentityWebApiAuthentication(Configuration, "AzureAd");
app.UseAuthentication();

// WeatherForecastController
[Authorize]

// appsettings.json
"AzureAd": {
    "Instance": "https://login.partner.microsoftonline.cn/",
    "ClientId": "eaaca060-36c7-4f8f-a7a2-0bac9d3d2bdf",
    "Domain": "ecolabcn.partner.onmschina.cn",
    "TenantId": "2c3c280f-2394-453f-944d-6df0dd9c338e",
    "Authority": "https://login.partner.microsoftonline.cn/2c3c280f-2394-453f-944d-6df0dd9c338e/"
}

@jmprieur
Copy link
Collaborator

@Gtyrande:

  1. Did you use Identity.Web 1.13.0 that we just released?
  2. Do you need to have the "Authority" property in the web API appsettings.json ? It should not be necessary (it will be computed from the Instance and Tenant ID
  3. What is the token version required by your API? (from the app registration: acceptedTokenVersion)

@Gtyrande
Copy link
Author

@jmprieur

  1. Yes. I update version in csproj to 1.13.0 and restored.
  2. I remove "Authority" property and the result is same.
  3. Do you mean this property in manifest: "accessTokenAcceptedVersion": null

@jmprieur
Copy link
Collaborator

Thanks @Gtyrande: yes. this is the right property. This means the web API is a v1.0 API.

Looking at the open id configuration: https://login.partner.microsoftonline.cn/common/.well-known/openid-configuration, the issuer is ending https://sts.chinacloudapi.cn/{tenantid}/.
Is the issuer in your access token the same?

@jlpstolwijk
Copy link

jlpstolwijk commented Jun 14, 2021

Since version 1.13, I get the above error (""The issuer '(null)' is invalid") when validating an access token in my API (ASP.NET 5.0). With version 1.12 all works fine.

Token is obtained using msal.js for angular v 2.0.0 (it sends a request to https://login.microsoftonline.com/organizations/oauth2/v2.0/token). Again, with Microsoft.Identity.Web 1.12.0, the token is validated just fine; in 1.13.0 I get an error about invalid issuer. As you can see in the below screenshot, the 'iss' claim is not null though, it is https://sts.windows.net/<my tenantId>/

appSettings.json:

	"AzureAd": {
		"Instance": "https://login.microsoftonline.com/",
		"Domain": "<my domain>",
		"TenantId": "organizations",
		"ClientId: "<my clientId>"
	},

startup.cs code (completely boilerplate):
services.AddAuthentication().AddMicrosoftIdentityWebApi(_config)

Example of decoded token in jwt.ms:
image

@ThomasBarnekow
Copy link

I have the same issue as @Gtyrande and @jlpstolwijk with 1.14.0, which I just installed. With 1.12.0, everything works as expected.

On the client side, I am using both Postman v8.7.0 and MSAL for Angular:

"@azure/msal-angular": "^2.0.0",
"@azure/msal-browser": "^2.14.2",

On the server side, I am using ASP.NET Core 5.0 with the following configuration:

appsettings.json

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "ClientId": "[guid]",
  "ClientSecret": "[removed]",
  "TenantId": "organizations"
},

Startup.ConfigureServices(IServiceCollection services)

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddMicrosoftGraph(Configuration.GetSection("Graph"))
    .AddInMemoryTokenCaches();

services.AddAuthorization(options =>
{
    options.AddPolicy("MinimumScope", policy => policy.RequireClaim("scp", "access_as_user"));
});

Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env)

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseSerilogRequestLogging();

    app.UseHttpsRedirection();
    app.UseRouting();

    // The UseCors call must be placed between UseRouting and UseAuthentication.
    // See https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-5.0#middleware-order.
    app.UseCors(CorsPolicyName);

    app.UseAuthentication();
    app.UseAuthorization();

    // Custom middleware must be placed between UseAuthorization and UseEndpoints.
    app.UseRoleBasedAccessControl();
    app.UseJsonApi();

    app.UseEndpoints(endpoints =>
    {
        // Require callers to be authenticated and have the minimum scope claim.
        endpoints.MapControllers().RequireAuthorization("MinimumScope");
    });
}

With app.UseRoleBasedAccessControl(), I am inserting my own custom middleware into the pipeline. With 1.14.0, the requests do not reach my custom middleware.

I've successfully decoded and validated the tokens using both jwt.ms and jwt.io:

{
  "aud": "api://[guid]",
  "iss": "https://sts.windows.net/[guid]/",
  "iat": 1626041859,
  "nbf": 1626041859,
  "exp": 1626045759,
  "acr": "1",
  "aio": "[removed]",
  "amr": [
    "pwd"
  ],
  "appid": "[guid]",
  "appidacr": "0",
  "email": "[email]",
  "family_name": "Barnekow",
  "given_name": "Thomas",
  "ipaddr": "[IP]",
  "name": "Thomas Barnekow",
  "oid": "[guid]",
  "preferred_username": "[email]",
  "rh": "[removed]",
  "scp": "access_as_user",
  "sub": "[removed]",
  "tid": "[guid]",
  "unique_name": "[email]",
  "upn": "[email]",
  "uti": "[guid]",
  "ver": "1.0"
}

As you see, the iss claim is not null. I am wondering why I am getting "ver": "1.0" tokens and do not know how to change that or whether that is an issue.

@ohadschn
Copy link

ohadschn commented Sep 18, 2021

Adding some keywords which would have saved me hours of research and debugging:

  • Sovereign cloud
  • National cloud
  • AzureChinaCloud
  • Mooncake
  • China

@shuichen17
Copy link

shuichen17 commented Jun 10, 2023

I use Microsoft.Identity.Web 1.25.3 and set "accessTokenAcceptedVersion": 2
Here is my code

services.AddAuthentication(options =>
                {
                    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer("AzureAd", jwtOptions =>
                {
                    jwtOptions.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = false
                    };
                }).AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));

              //  Set up basic authorization
                services.AddAuthorization(options =>
                {
                    options.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
                    .RequireAuthenticatedUser().Build());
                });

It works properly. My app is multitenant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working css This issue is also a support case or similar to a support case in progress enhancement New feature or request external fixed P1 question Further information is requested
Projects
None yet
Development

No branches or pull requests

8 participants