question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Missing claims using Introspection

See original GitHub issue

Confirm you’ve already contributed to this project or that you sponsor it

  • I confirm I’m a sponsor or a contributor

Version

3.x

Question

Hello, I have 1 application which can work in standalone or proxy mode. In standalone mode an instance is responsible for verifying his tokens. In proxy mode token is generated on master instance and proxy verifies if token contain all required claims. We are using Yarp to forward requests to master instance.

First I configure my OpenIdDict to use local server in validation method but because these 2 applications have different signing keys, I had to change it to use introspection. However I notice that token doesn’t contain all claims which I can see on jwt.io (e.g. oi_tkn_id, scope).

I notice that configure method doesn’t work in my case. I tried to explain server to not validate signing key but it doesn’t work. I get this error message: The signing key associated to the specified token was not found.

services.AddOpenIddict()
                .AddCore(options =>
                {
                    options.UseEntityFrameworkCore()
                        .UseDbContext<ApplicationDbContext>()
                        .ReplaceDefaultEntities<Client, Authorization, Scope, Token, int>();
                })
                .AddServer(options =>
                {
                    options
                        .SetTokenEndpointUris("/connect/token")
                        .SetRevocationEndpointUris("/connect/revocation")
                        .SetIntrospectionEndpointUris("/connect/introspect");

                    options.AddEventHandler<OpenIddictServerEvents.ProcessSignInContext>(builder =>
                    {
                        builder.UseInlineHandler(context =>
                        {
                            if (context.Transaction.Request != null)
                            {
                                context.Response["scope"] = string.Join(" ", context.Transaction.Request.GetScopes().OrderBy(z => z));
                            }

                            return default;
                        });
                    });

                    options.AddEventHandler<OpenIddictServerEvents.ProcessChallengeContext>(builder =>
                    {
                        builder.UseInlineHandler(context =>
                        {
                            var authPropertiesKey = typeof(AuthenticationProperties).ToString();
                            if (context.Transaction.Properties.ContainsKey(authPropertiesKey))
                            {
                                var props = context.Transaction.Properties[authPropertiesKey] as AuthenticationProperties;
                                context.Response["message"] = props.Items["message"];
                            }

                            return default;
                        });
                    });

                    options.AllowClientCredentialsFlow();
                    options.AllowPasswordFlow();
                    options.AllowRefreshTokenFlow();

                    options.UseReferenceRefreshTokens();

                    options.RegisterScopes(
                        OpenIddictConstants.Permissions.Scopes.Profile.Replace(OpenIddictConstants.Permissions.Prefixes.Scope, string.Empty),
                        OpenIddictConstants.Permissions.Scopes.Roles.Replace(OpenIddictConstants.Permissions.Prefixes.Scope, string.Empty),
                        CustomScopes.APPLICATION,
                        CustomScopes.IDENTITY_SETUP,
                        CustomScopes.SUPPORT_PACKAGE);

                    options.SetAccessTokenLifetime(TimeSpan.FromHours(1));
                    options.SetRefreshTokenLifetime(TimeSpan.FromDays(7));

                    options.AddEncryptionCertificate(signingCertificate)
                        .AddSigningCertificate(signingCertificate);

                    options.DisableAccessTokenEncryption();

                    options.UseAspNetCore()
                        .EnableTokenEndpointPassthrough();
                })
                .AddValidation(options =>
                {
                    options.Configure(c =>
                    {
                        c.TokenValidationParameters.ValidateIssuer = false;
                        c.TokenValidationParameters.ValidateIssuerSigningKey = false;
                    });

                    options.SetIssuer("https://localhost:44322/");

                    options.UseIntrospection()
                        .SetClientId(GeneralConstants.APP_CLIENT_ID)
                        .SetClientSecret(GeneralConstants.APP_CLIENT_SECRET);

                    options.UseSystemNetHttp();

                    //options.UseLocalServer();

                    options.UseAspNetCore();
                });

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Comments:25 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
MDzygacommented, Dec 1, 2022

Thanks @kevinchalet, we rediscussed our architecture and we will change like you said. So, we will use introspection and issuer has to confirm token.

0reactions
MDzygacommented, Dec 7, 2022

Hi @kevinchalet, I fixed my all issues 😃 Thank you for your helping 😃 I would like to use ChangeToken but currently I don’t understand how to use it with openIdDict configuration. I attached my current solution for others.

services.AddOpenIddict()
                .AddCore(options =>
                {
                    options.UseEntityFrameworkCore()
                        .UseDbContext<ApplicationDbContext>()
                        .ReplaceDefaultEntities<Client, Authorization, Scope, Token, int>();
                })
                .AddServer(options =>
                {
                    options
                        .SetTokenEndpointUris("/connect/token")
                        .SetRevocationEndpointUris("/connect/revocation")
                        .SetIntrospectionEndpointUris("/connect/introspect");

                    options.AddEventHandler<OpenIddictServerEvents.ProcessSignInContext>(builder =>
                    {
                        builder.UseInlineHandler(context =>
                        {
                            if (context.Transaction.Request != null)
                            {
                                context.Response["scope"] = string.Join(" ", context.Transaction.Request.GetScopes().OrderBy(z => z));
                            }

                            return default;
                        });
                    });

                    options.AddEventHandler<OpenIddictServerEvents.ProcessChallengeContext>(builder =>
                    {
                        builder.UseInlineHandler(context =>
                        {
                            var authPropertiesKey = typeof(AuthenticationProperties).ToString();
                            if (context.Transaction.Properties.ContainsKey(authPropertiesKey))
                            {
                                var props = context.Transaction.Properties[authPropertiesKey] as AuthenticationProperties;
                                context.Response["message"] = props.Items["message"];
                            }

                            return default;
                        });
                    });

                    options.AllowClientCredentialsFlow();
                    options.AllowPasswordFlow();
                    options.AllowRefreshTokenFlow();

                    options.UseReferenceRefreshTokens();

                    options.RegisterScopes(
                        OpenIddictConstants.Permissions.Scopes.Profile.Replace(OpenIddictConstants.Permissions.Prefixes.Scope, string.Empty),
                        OpenIddictConstants.Permissions.Scopes.Roles.Replace(OpenIddictConstants.Permissions.Prefixes.Scope, string.Empty),
                        CustomScopes.APPLICATION,
                        CustomScopes.IDENTITY_SETUP,
                        CustomScopes.SUPPORT_PACKAGE);

                    options.SetAccessTokenLifetime(TimeSpan.FromHours(1));
                    options.SetRefreshTokenLifetime(TimeSpan.FromDays(7));

                    options.AddEncryptionCertificate(signingCertificate)
                        .AddSigningCertificate(signingCertificate);

                    options.DisableAccessTokenEncryption();

                    options.UseAspNetCore()
                        .EnableTokenEndpointPassthrough();
                })
                .AddValidation(options =>
                {
                    if (!string.IsNullOrWhiteSpace(MasterUrlManager.Get().Host))
                    {
                        string clientId = LocalClientManager.GetId();
                        string clientSecret = LocalClientManager.GetSecret();
                        string localIssuer = $"https://localhost:{hostSettings.SSLPortNumber}/";

                        options.SetIssuer(localIssuer);
                        options.AddAudiences(clientId);

                        options.UseIntrospection()
                            .SetClientId(clientId)
                            .SetClientSecret(clientSecret);

                        options.UseSystemNetHttp();

                        options.AddEventHandler<OpenIddictValidationEvents.PrepareIntrospectionRequestContext>(builder =>
                        {
                            builder.UseInlineHandler(c =>
                            {
                                MasterUrlManager master = MasterUrlManager.Get();
                                string issuer = MasterUrlHelper.GetHttpsUrl(master.Host, master.HttpsPort);

                                c.Options.Issuer = new Uri(master.IsHealthy && !string.IsNullOrWhiteSpace(issuer) ? $"{issuer}/" : localIssuer);
                                c.Options.ConfigurationManager.RequestRefresh();

                                return default;
                            });
                        });

                        options.Configure(c =>
                        {
                            MasterUrlManager master = MasterUrlManager.Get();
                            string issuer = MasterUrlHelper.GetHttpsUrl(master.Host, master.HttpsPort);

                            c.Issuer = new Uri(master.IsHealthy && !string.IsNullOrWhiteSpace(issuer) ? $"{issuer}/" : localIssuer);
                        });
                    }
                    else
                    {
                        options.UseLocalServer();
                    }

                    options.UseAspNetCore();
                });
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to get all claims for a reference token? · Issue #2313
Hi, I'm using reference tokens and a mix of resource owner credentials flow, client credentials flow and a custom grant.
Read more >
Token Introspection Endpoint - OAuth 2.0 Simplified
This enables a resource server to validate access tokens without a network call, by validating the signature and parsing the claims within the ......
Read more >
OAuth 2.0 token introspection endpoint
The resource server authenticates at the token introspection endpoint with the registered method, set by the token_endpoint_auth_method metadata parameter.
Read more >
Reference Tokens and Introspection - leastprivilege.com
Self-contained tokens are using a protected, time-limited data structure that contains metadata and claims to communicate the identity of the ...
Read more >
IdentityServerV4 Reference Token Introspection
So my take away from this is that there is some link missing between the API and the token that was issued, but...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found