简体   繁体   中英

Validate IdentityServer4 token in Web API (.Net framework)

I would like to validate the token generated from IdentityServer in Web API(.Net Framework 4.7.1).

Here is what I've done so far in Startup.cs in Web API

public void Configuration(IAppBuilder app)
{

    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = "Cookies"
    });

    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            RequireHttpsMetadata = false,
            SignInAsAuthenticationType = "Cookies",
            Authority = "https://localhost:44380/",
            RedirectUri = "http://localhost:4200/auth-callback",
            ClientId = "angular",
            Scope = "api1",
            ResponseType = "code"
        });

}

It throws code challenge required error.

Due to the design constraint, I will not be able to use the IdentityServer/IdentityServer3.AccessTokenValidation and I should use UseOpenIdConnectAuthentication to validate the token.

Edit I was able to get this working in Web API Core. Here is my Startup.cs of Web API Core. But not sure how to do this in Web API .Net Framework. I also tried with IdentityServer/IdentityServer3.AccessTokenValidation with below configuration but it throws 401 error

public void Configuration(IAppBuilder app)
{
    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
    {
        Authority = "https://localhost:44380",
        RequiredScopes = new[] { "api1" }
    });
}

Due to the design constraint, I will not be able to use the IdentityServer/IdentityServer3.AccessTokenValidation and I should use UseOpenIdConnectAuthentication to validate the token.

The conclusion is totally wrong. OpenIdConnectAuthentication is for interactive sign-in, not for bearer token validation. You can use IdentityServer3.Contrib.AccessTokenValidation instead.

I have prepared a working repo , for you and more for myself. It targets 4.7.2. Everything's hardcoded, but the only configuration block is in the startup.cs

public void Configuration(IAppBuilder app)
{
    app.UseIdentityServerBearerTokenAuthentication(new 
    IdentityServerBearerTokenAuthenticationOptions
    {
        Authority = "https://demo.identityserver.io/",
        RequiredScopes = new[] { "api" }
    });
}

As you can see, I utilized the public Identityserver instance.

I used curl To get the token:

curl -d "grant_type=client_credentials&client_id=client&client_secret=secret" https://demo.identityserver.io//connect/token

And to call my API:

curl -v  -H "Accept: application/json" -H "Authorization: Bearer <The token is here>"  http://localhost/MVCBearerNuget/api/TestApi

The answer was:

< HTTP/1.1 200 OK
< Cache-Control: no-cache
< Pragma: no-cache
< Content-Type: application/json; charset=utf-8
< Expires: -1
< Server: Microsoft-IIS/10.0
< X-AspNet-Version: 4.0.30319
< X-Powered-By: ASP.NET
< Date: Tue, 10 Sep 2019 17:37:08 GMT
< Content-Length: 19
<
["value1","value2"]* Connection #0 to host localhost left intact

An alternative is to build the middleware yourself, but the one I targeted is up to date, easy to use and it definitely works.

I have used .NET framework 4.6.1 for creating Web API, For Identity Provider, I am using Identity Server 4 (Earlier I used Identity Server 3). Initially I did face a problem, but I came up with this workaround which worked perfectly to me. Note that I am using ClientCredentials grantflow.

I am using the same IdentityServer3.AccessTokenValidation library for token validation. The trick is to target to Introspection end point. Below is my configuration which worked.

Here is the configuration for Web API, Note that setting setting ValidationMode property is crucial.

app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
        {
            Authority = ConfigurationManager.AppSettings["AuthServerURI"],
            RequiredScopes = new[] { "comp-read", "stats-read" },
            ClientId = "apiname",
            ClientSecret = "apisecret",
            ValidationMode = ValidationMode.ValidationEndpoint,
            EnableValidationResultCache = true
        });

This is how the APIResource and Client is configured in my IDP.

new ApiResource
            {
                Name = "apiname",
                DisplayName = "Web API",
                Description = "Access to Web API Services",
                ApiSecrets = new List<Secret> {new Secret("apisecret".Sha256())},
                Scopes = new List<Scope> {
                    new Scope("comp-read", "Read access to Comp Db API"),
                    new Scope("stats-read", "Read access to Stats API")
                }

This is how one of the client is configured.

new Client
            {
                ClientName = "name of the client",
                ClientId = "clientname",
                Enabled = true,
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                ClientSecrets = new List<Secret> {
                    new Secret("secretforclient".Sha256())
                },
                AllowedScopes = new List<string>
                {
                    "stats-read"
                },
                AccessTokenLifetime = 1000
            }

Hopefully this helps. Thanks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM