Multiple cname for single openid app

The Okta server is configured to have multiple redirect urls. The problem came about as the same app is servicing multiple domains (via SNI where multiple domains point to the same IP and port number) and sub-domains and need to authenticate using the same client. We determine the app by the client URL from the request.
Now, to authenticate the client, i need to use the proper redirect url. Say, if the web service is deployed on 127.0.0.1 IP address and i have https://client1.test.com, https://client2.com, https://Client3.com , etc domains all point to the 127.0.0.1.
Is there a way to configure the client to use delegate or something to pull redirect URI dynamically rather than having it configured in advance. At this point the only solution is to deploy multiple apps, each separate app for each domain, where as we need one app and to be able to handle multiple domains.

Which client are you using?

If you are doing a SPA or Web flow, your application should know what domain you are rendering the page for as part of the request or url. You can then configure the client to set the right redirect url.

You can have multiple redirect URL per application in Okta.

Hi Tom

I am using example code for .Net MVC ,

In Owin Startup I am unable to get Application Url , as request is not formed yet, but that is the only point where we can set redirect url , even after we try to set redirect url but it always take the first-time setted redirecturl.

                    RedirectToIdentityProvider = context =>

{

                           context.ProtocolMessage.RedirectUri = redirectUri;////

                           context.ProtocolMessage.PostLogoutRedirectUri = postLogoutRedirectUri;/////

                           //other code

                            return Task.FromResult(true);

                    },

@nate.barbettini any ideas here?

@atifbashir The limitation here is that the OWIN stack gets configured at app boot time. You should be able to override configuration on a per-request basis, so I’m surprised your RedirectToIdentityProvider code didn’t work (that’s what I would have tried).

Let me do some testing and I’ll let you know if I discover a workaround.

I just tried it with version 4.0 of Owin.Host.SystemWeb and Owin.Security.OpenIdConnect and the RedirectToIdentityProvider code worked as expected:

RedirectToIdentityProvider = n =>
{
    if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
    {
        // Not the same redirectUri as my OWIN configuration
        n.ProtocolMessage.RedirectUri = "https://adifferentdomain.example.com/foobar";
    }
}

The if isn’t required, but I used that so I can control login and logout separately if I need to.

If this still isn’t working for you, try the newest version of the OWIN libraries. Or maybe there’s something else in your code that’s causing this to break. If you want to share more of your code I can take a look.

1 Like

Still not working for me even update to Owin 4

Code is here

public void ConfigureAuth(IAppBuilder app)
{

    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
    });

    var issuer = ConfigurationManager.AppSettings["okta:Issuer"].ToString();
    var clientId = ConfigurationManager.AppSettings["okta:ClientId"].ToString();
    var clientSecret = ConfigurationManager.AppSettings["okta:ClientSecret"].ToString();
    var redirectUri =  ConfigurationManager.AppSettings["okta:C1RedirectUri"].ToString();
    var postLogoutRedirectUri =  ConfigurationManager.AppSettings["okta:C1PostLogoutRedirectUri"].ToString();

    try
    {
        var url = System.Web.HttpContext.Current.Request.UrlReferrer.AbsoluteUri.ToString();

        if (url.ToLower().Contains("C1.net"))
        {
            redirectUri = ConfigurationManager.AppSettings["okta:RedirectUri"].ToString();
            postLogoutRedirectUri = ConfigurationManager.AppSettings["okta:PostLogoutRedirectUri"].ToString();
        }

        if (url.ToLower().Contains("C2.net"))
        {
            redirectUri = ConfigurationManager.AppSettings["okta:C1RedirectUri"].ToString();
            postLogoutRedirectUri = ConfigurationManager.AppSettings["okta:C1PostLogoutRedirectUri"].ToString();
        }

        if (url.ToLower().Contains("C3.com"))
        {
            redirectUri = ConfigurationManager.AppSettings["okta:C2RedirectUri"].ToString();
            postLogoutRedirectUri = ConfigurationManager.AppSettings["okta:C2PostLogoutRedirectUri"].ToString();
        }
    }

    catch (Exception ex)
    {
        //todo
    }

#if DEBUG

    issuer = ConfigurationManager.AppSettings["okta:DevIssuer"].ToString();
    redirectUri = ConfigurationManager.AppSettings["okta:DevRedirectUri"].ToString();
    postLogoutRedirectUri = ConfigurationManager.AppSettings["okta:DevPostLogoutRedirectUri"].ToString();

#endif

    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        ClientId = clientId,
        ClientSecret = clientSecret,
        Authority = issuer,
        RedirectUri = redirectUri,
        ResponseType = "code id_token",//"Refresh Token",//
        UseTokenLifetime = false,
        Scope = "openid profile",
        SignInAsAuthenticationType = "Cookies",
        PostLogoutRedirectUri = postLogoutRedirectUri,
        TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
        {
            NameClaimType = "name"
        },

        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            //remove nonce error
            AuthenticationFailed = (context) =>
            {
                if (context.Exception.Message.StartsWith("OICE_20004" ) || context.Exception.Message.Contains("IDX10311"))
                {
                    context.SkipToNextMiddleware();
                    return Task.FromResult(0);
                }

                return Task.FromResult(0);
            },

            SecurityTokenValidated = async n =>
            {
                var token = n.ProtocolMessage.AccessToken;

                if (!string.IsNullOrEmpty(token))
                {
                    n.AuthenticationTicket.Identity.AddClaim(
                        new Claim("access_token" , token));
                }
            },

            RedirectToIdentityProvider = context =>
            {
                context.ProtocolMessage.RedirectUri = redirectUri;////
                context.ProtocolMessage.PostLogoutRedirectUri = postLogoutRedirectUri;/////

                if (context.ProtocolMessage.RequestType.Equals(OpenIdConnectRequestType.LogoutRequest))
                {
                    var idToken = context.OwinContext.Authentication.User.Claims.FirstOrDefault(c => c.Type == "id_token")?.Value;
                    context.ProtocolMessage.IdTokenHint = idToken;
                }

                return Task.FromResult(true);
            },

            AuthorizationCodeReceived = async context =>
            {
                // Exchange code for access and ID tokens

                var tokenClient = new TokenClient(
                    issuer + "/oauth2/v1/token", clientId, clientSecret);

                var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(context.ProtocolMessage.Code, redirectUri);
                if (tokenResponse.IsError)
                {
                    throw new Exception(tokenResponse.Error);
                }

                var userInfoClient = new UserInfoClient(issuer + "/oauth2/v1/userinfo");

                var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                var identity = new ClaimsIdentity();
                identity.AddClaims(userInfoResponse.Claims);
                identity.AddClaim(new Claim("id_token", tokenResponse.IdentityToken));
                identity.AddClaim(new Claim("access_token", tokenResponse.AccessToken));

                if (!string.IsNullOrEmpty(tokenResponse.RefreshToken))
                {
                    identity.AddClaim(new Claim("refresh_token", tokenResponse.RefreshToken));
                }

                var nameClaim = new Claim(ClaimTypes.Name, userInfoResponse.Claims.FirstOrDefault(c => c.Type == "name")?.Value);
                identity.AddClaim(nameClaim);

                context.AuthenticationTicket = new AuthenticationTicket(
                    new ClaimsIdentity(identity.Claims, context.AuthenticationTicket.Identity.AuthenticationType),
                    context.AuthenticationTicket.Properties);
            }
        }
    });
}

The problem is here:

var url = System.Web.HttpContext.Current.Request.UrlReferrer.AbsoluteUri.ToString();

The code in Startup.cs is evaluated when the application starts up, not when a request arrives. So, the above code won’t do anything because there is no HttpContext.Current.Request yet.

The code in RedirectToIdentityProvider does run at request time, though. You just need to move your if…contains checks into the RedirectToIdentityProvider block.

See this answer on Stack Overflow: OWIN OpenIdConnect middleware - set RedirectUri dynamically

1 Like