Base solution for your next web application
Open Closed

How can I enable both okta and auth0 for a tenant using openid #12204


User avatar
0
kansoftware created

I want to enable both okta and auth0 for a single tenant as some users may login through okta and some through auth0. I am having a multitenant application. Do I need to custom the code or there is a functionality in the base code. Could you please help me out how can I achieve that

Markdown is supported
Copy & paste or drag & drop images (max 30 MB per image)

145 Answer(s)
  • User Avatar
    0
    kansoftware created

    AbpOpenIdConnectHandler handles the callback for external login.

    Callback url is https://localhost/signin-oidc

    Ok thanks. For one tenant I have configured Okta authentication. For Okta I only logout from the application not from Okta. But when I hit on login after logout it gives me error

    ERROR 2025-04-23 10:18:09,922 [188  ] idateAntiforgeryTokenAuthorizationFilter - The provided antiforgery token was meant for a different claims-based user than the current user.
    Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The provided antiforgery token was meant for a different claims-based user than the current user.
       at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext)
       at Abp.AspNetCore.Mvc.Antiforgery.AbpValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)
    WARN  2025-04-23 10:18:27,423 [154  ] Mvc.Authorization.AbpAuthorizationFilter - Abp.Authorization.AbpAuthorizationException: Current user did not login to the application!
       at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(IEnumerable`1 authorizeAttributes)
       at Abp.Authorization.AuthorizationHelper.CheckPermissionsAsync(MethodInfo methodInfo, Type type)
       at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(MethodInfo methodInfo, Type type)
       at Abp.AspNetCore.Mvc.Authorization.AbpAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)
    Abp.Authorization.AbpAuthorizationException: Current user did not login to the application!
       at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(IEnumerable`1 authorizeAttributes)
       at Abp.Authorization.AuthorizationHelper.CheckPermissionsAsync(MethodInfo methodInfo, Type type)
       at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(MethodInfo methodInfo, Type type)
       at Abp.AspNetCore.Mvc.Authorization.AbpAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)
    

    And as soon I clear the browser cache data it works at that point of time.

    Steps:

    1. Login with Okta
    2. Logout (Only from my application)
    3. Login with Okta
    4. Error
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    Can these steps be reproduced in maliming/CDP-Base-Zero-13.0.0?

    • Login with Okta
    • Logout (Only from my application)
    • Login with Okta
    • Error

    What does this step mean, * Logout (Only from my application)?

    The provided antiforgery token was meant for a different claims-based user than the current user.

    This means that the current user has changed, but the antiforgery token was not refreshed in time.

    Thanks.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    I want to auth0 (openid provider) access token to access my application instead of dot net zero token. How can i achieve this with the customized changes we did for openid provider

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    This question has too many replies.

    Can you please create a new question?

    Thanks.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: hi

    This question has too many replies.

    Can you please create a new question?

    Thanks.

    Ok in short I want to use Auth0 Access Token to access the API's instead of dot net zero jwt token

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    The API is an ABP application, and you need to use its access token for authentication.

    Why do you want to use Auth0 Access Token?

    It may not include user information from ABP

    Thanks

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: hi

    The API is an ABP application, and you need to use its access token for authentication.

    Why do you want to use Auth0 Access Token?

    It may not include user information from ABP

    Thanks

    There are some use cases like multiple database against a tenant and a mediator application which will connect to a third party AI. Another few cases are also there. Therefore we would like to use auth0 access token to access our api's. Some information like tenant id, user id can be brought from claims but yes we need to set that details in abpsession.

    Could you please help me with the steps I need to take to achieve this

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    If there is an HTTP request to your API app, and the request header contains an Auth0 access_token.

    In this case. You can add a new middleware and retrieve and verify this access token. Get all claims from this token. after that, set your claims to HttpContext.User.

    app.UseAuthentication();
    
    app.Use(async (httpContext, next) =>
    {
        if (httpContext.User.Identity != null && httpContext.User.Identity.IsAuthenticated)
        {
            // Skip for authenticated users
            await next(httpContext);
            return;
        }
    
        var authorization = httpContext.Request.Headers["Authorization"].FirstOrDefault();
        var bearerToken = authorization?.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase) == true
            ? authorization.Substring("Bearer ".Length).Trim()
            : null;
    
        if (bearerToken != null)
        {
            //Check the token is valid here
            // assuming you have get the user claims from the token
            var claims = new List<Claim>());
    
            httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(claims));
    
            //After that, IAbpSession will get the user information from the httpContext.User
        }
    
        await next(httpContext);
    });
    
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    I have set up a middleware

    using Microsoft.AspNetCore.Http;
    using Microsoft.IdentityModel.Tokens;
    using System.IdentityModel.Tokens.Jwt;
    using System;
    using Microsoft.Extensions.Configuration;
    using System.Threading.Tasks;
    using System.Linq;
    using System.Net.Http;
    using Newtonsoft.Json;
    using System.Security.Claims;
    using System.Threading;
    using CDP.Authorization.Users;
    using CDP.MultiTenancy;
    using static CDP.MultiTenancy.TenantAppService;
    using Microsoft.AspNetCore.Authentication;
    using System.Security.Principal;
    using Abp.Runtime.Session;
    namespace CDP.Middleware
    {
        public class Auth0JwtMiddleware
        {
            private readonly RequestDelegate _next;        
            private readonly TenantAppService _tenantAppService;
    
            public Auth0JwtMiddleware(RequestDelegate next, TenantAppService tenantAppService)
            {
                _next = next;
                _tenantAppService = tenantAppService;
            }
    
            public async Task InvokeAsync(HttpContext context)
            {
                if (context.User.Identity != null && context.User.Identity.IsAuthenticated)
                {
                    // Skip for authenticated users
                    await _next(context);
                    return;
                }
    
                var token = ExtractTokenFromHeader(context);
    
                if (!string.IsNullOrEmpty(token))
                {
                    await ValidateAuth0Token(context, token);
                }
    
                await _next(context);
            }
    
            private string ExtractTokenFromHeader(HttpContext context)
            {
                var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();
                if (authHeader?.StartsWith("Bearer ") == true)
                {
                    return authHeader.Substring("Bearer ".Length).Trim();
                }
                return null;
            }
    
            private async Task ValidateAuth0Token(HttpContext context, string token)
            {
                try
                {                
                    var settings = LoadTenantAuthSettings();
                    var domain = settings.Domain;
                    var audience = settings.Audience;
    
                    var tokenHandler = new JwtSecurityTokenHandler();
                    var validationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKeyResolver = (token, securityToken, kid, parameters) =>
                        {
                            var client = new HttpClient();
                            var keyUri = $"https://{domain}/.well-known/jwks.json";
                            var response = client.GetAsync(keyUri).Result;
                            var keys = response.Content.ReadAsStringAsync().Result;
                            var jwks = JsonConvert.DeserializeObject<JsonWebKeySet>(keys);
                            return jwks.Keys;
                        },
                        ValidateIssuer = true,
                        ValidIssuer = $"https://{domain}/",
                        ValidateAudience = true,
                        ValidAudiences = new[] { audience, $"https://{domain}/userinfo" },
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.Zero                    
                    };
    
                    var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);                
                    var identity = (ClaimsIdentity)principal.Identity;
    
                    // Required for ABP session
                    //if (identity != null)
                    //{
                    //    var toRemove = identity.FindFirst(ClaimTypes.NameIdentifier);
                    //    var existing = identity.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
                    //    if (existing != null)
                    //    {
                    //        identity.RemoveClaim(existing);
                    //    }
                    //    identity.AddClaim(new Claim(AbpClaimTypes.UserId, "3"));
                    //    identity.AddClaim(new Claim(AbpClaimTypes.TenantId, "2"));
                    //    identity.AddClaim(new Claim("http://www.aspnetboilerplate.com/identity/claims/userName", "admin"));
                    //    identity.AddClaim(new Claim("http://www.aspnetboilerplate.com/identity/claims/emailAddress", "[email protected]"));
    
                    //}
                    Thread.CurrentPrincipal = principal;
                    context.User = principal;
                }
                catch (Exception ex)
                {
                    try
                    {
                        IIdentity? identity = context.User.Identity;
                        if (identity == null || !identity.IsAuthenticated)
                        {
                            AuthenticateResult result = await context.AuthenticateAsync("Bearer");
                            if (result.Succeeded && result.Principal != null)
                            {
                                context.User = result.Principal;
                            }
                        }                    
                    }
                    catch(Exception ex1)
                    {
                        context.Response.StatusCode = 401;
                        await context.Response.WriteAsync("Unauthorized");
                        return;
                    }
                    
                }
            }
    
            private Auth0Settings LoadTenantAuthSettings(int tenantId=2)
            {
                Auth0Settings auth0Settings = new Auth0Settings();
                auth0Settings = _tenantAppService.LoadTenantAuthSettings(tenantId);
                return auth0Settings;
            }
        }
    }
    
    

    Now how can I pass tenant id in function LoadTenantAuthSettings?

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    Now how can I pass tenant id in function LoadTenantAuthSettings?

    Can you add a tenant id claim to your Auth0 access token?

    Thanks.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: hi

    Now how can I pass tenant id in function LoadTenantAuthSettings?

    Can you add a tenant id claim to your Auth0 access token?

    Thanks.

    I got it. Thanks if I want to use auth0 token in the browser also to access my API's what changes I need to make? I am using javascript as frontend language

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    You just need to include the access token correctly in the request header.

    Thanks.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: You just need to include the access token correctly in the request header.

    Thanks.

    Can you please guide me what custom changes I need to do and in which files

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    What type of project do you have? I can't quite remember.

    If you're not using the automatically generated JS code from ABP, where does your JS get the auth0 token from?

    Thanks.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: hi

    What type of project do you have? I can't quite remember.

    If you're not using the automatically generated JS code from ABP, where does your JS get the auth0 token from?

    Thanks.

    I am using the ABP JS code only.

    Also randomly I am facing the below errors ERROR 2025-07-22 14:01:06,253 [201 ] idateAntiforgeryTokenAuthorizationFilter - The antiforgery cookie token and request token do not match. Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The antiforgery cookie token and request token do not match. at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext) at Abp.AspNetCore.Mvc.Antiforgery.AbpValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)

    ERROR 2025-07-22 20:23:15,035 [116 ] idateAntiforgeryTokenAuthorizationFilter - The required antiforgery header value "X-XSRF-TOKEN" is not present. Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The required antiforgery header value "X-XSRF-TOKEN" is not present. at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext) at Abp.AspNetCore.Mvc.Antiforgery.AbpValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)

    ERROR 2025-07-23 13:47:50,279 [153 ] idateAntiforgeryTokenAuthorizationFilter - The provided antiforgery token was meant for a different claims-based user than the current user. Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The provided antiforgery token was meant for a different claims-based user than the current user. at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext) at Abp.AspNetCore.Mvc.Antiforgery.AbpValidateAntiforgeryTokenAuthorizationFilter.OnAuthorizationAsync(AuthorizationFilterContext context)

    Not sure what does actually this error means

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    Can you push your changes to https://github.com/maliming/CDP-Base-Zero-13.0.0?

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: hi

    Can you push your changes to https://github.com/maliming/CDP-Base-Zero-13.0.0?

    This repo has the latest code.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    But it hasn't been updated in 4 months.

    ERROR 2025-07-22 14:01:06,253 [201 ] idateAntiforgeryTokenAuthorizationFilter - The antiforgery cookie token and request token do not match.

    I'm asking because I need to this repository to reproduce the AntiforgeryValidationException

    Thanks.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: But it hasn't been updated in 4 months.

    ERROR 2025-07-22 14:01:06,253 [201 ] idateAntiforgeryTokenAuthorizationFilter - The antiforgery cookie token and request token do not match.

    I'm asking because I need to this repository to reproduce the AntiforgeryValidationException

    Thanks.

    Yes this is the base code and I implemented my open id connect work in this repo only. The issue is old, but reported now. So, this repo has the latest work. I tried to replicate it through some steps but wasn't successful

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    If it doesn't cause any functional issues, you can temporarily ignore it.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: If it doesn't cause any functional issues, you can temporarily ignore it.

    No, it is causing issue to our end users, as randomly they face the below error

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    You can try disabling Antiforgery for the specified pages.

    
    context.Services.AddRazorPages(options =>
    {
        options.Conventions.AddPageApplicationModelConvention("/Account/Login", model =>
        {
            model.Filters.Add(new IgnoreAntiforgeryTokenAttribute());
        });
    });
    
    
    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: AddPageApplicationModelConvention

    Where should I add this code? Also what's the actual cause of this issue? Also what actually does this Antiforgery token does?

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    Add it to your Web project.

    This anti-request-forgery feature will be disabled

    https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-9.0

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)
  • User Avatar
    0
    kansoftware created

    [maliming] said: hi

    Add it to your Web project.

    This anti-request-forgery feature will be disabled

    https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-9.0

    Instead of temporarily ignoring it, are there any steps or specific functionality which I can check to find out the actual cause

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)