9

Is there any way how can I set RedirectUri property for OpenIdConnectMessage based on a Request scope, not Application scope?

My app is serving multiple domains (myapp.com, myapp.fr, ..) and based on domain, it determine default language for the content. I need that the user is taken back to the same domain after login thru IdP so I need to find a way how RedirectUri is set per request scope rather than app scope as done by configuring middleware options in startup.cs .

Antonin Jelinek
  • 2,277
  • 2
  • 20
  • 25

4 Answers4

18

This can be done via Notification event RedirectToIdentityProvider . Something like this:

 Notifications = new OpenIdConnectAuthenticationNotifications
                 {
                     RedirectToIdentityProvider = async n =>
                     {
                         n.ProtocolMessage.RedirectUri = n.OwinContext.Request.Uri.Host;
                         n.ProtocolMessage.PostLogoutRedirectUri = n.OwinContext.Request.Uri.Host;
                     },
                     //other notification events...
                 }

`

Antonin Jelinek
  • 2,277
  • 2
  • 20
  • 25
  • you saved me, i totally forgot about events. i had to dynamically change clientId. – sensei Sep 15 '17 at 16:36
  • 2
    I know this is an old question, but I'm working on a legacy .NET framework 4.7.2 app. I'm trying to use this approach to dynamically set the `RedirectUri` inside RedirectToIdentityProvider, but it causes an Exception `Error: 'invalid_grant'. Error_Description (may be empty): 'Incorrect redirect_uri'.` However it works fine if I only set the `RedirectUrl` property on app startup in `OpenIdConnectAuthenticationOptions`. I can't find any other references online to altering the RedirectUri causing this issue. Any suggestions? – Chris Jul 05 '21 at 16:44
  • 1
    Just a note for anybody reading Chris's comment above: this error is coming back from the identity provider, so it means that the application and the IdP is not configured to accept the redirect_url parameter passed in the HTTP request and the beginning of the flow. – Joel Mussman Oct 18 '21 at 04:51
5

If you're using ResponseType = OpenIdConnectResponseType.CodeIdToken, it's necessary to set RedirectUri in several notification events.

In the AuthorizationCodeReceived notification, you can set the RedirectUri on TokenEndpointRequest to ensure the same value is also passed in the token request.

RedirectToIdentityProvider = n =>
{
    n.ProtocolMessage.RedirectUri = redirectUrl;
    // other settings   
}
AuthorizationCodeReceived = n =>
{
    n.TokenEndpointRequest.RedirectUri = redirectUrl;
    // other settings   
}
Chris
  • 201
  • 4
  • 9
  • This was the fix for me. I was using ProtocolMessage in both and there was no redirecturi in the request. Changing AuthorizationCodeReceived to TorkenEndPointRequest made it work. – SpokaneDJ Nov 30 '22 at 20:06
2

I know this is an old post and the answer is already mentioned. But it still took me a while to figure out how to set the dynamic RedirectUri.

I was assigning RedirectUri in OpenIdConnectAuthenticationOptions and RedirectToIdentityProvider, which was causing issues.

We should assign RedirectUri only in RedirectToIdentityProvider event.

For someone who needs help, you can check my code here

Harshal
  • 105
  • 4
0

When you publish your site to Microsoft Azure with multiples domains pointing to the same site and turns on: Authentication-> Allow unauthenticated access (your site have public and private pages); Microsoft Azure randomly call back one of your Redirect URIs. To control this random behavior, you need to explicit set RedirectUri property base on Owin Context Request.

enter image description here

Don't ask me why, also you need to change URIs address removing “.auth/login/aad/callback” except for localhost. (If anyone knows the reason for this please let me know)

This works code works for me:

    public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectUri,

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    AuthenticationFailed = (context) =>
                    {
                        return System.Threading.Tasks.Task.FromResult(0);
                    },
                    RedirectToIdentityProvider = (context) =>
                    {
                        string strPostLogoutRedirectUri;
                        string strRedirectUri = EnsureTrailingSlash(context.OwinContext.Request.Uri.ToString());

                        int nPos = strRedirectUri.IndexOf("://");
                        if (nPos > 0)
                        {
                            nPos += 3;
                            strPostLogoutRedirectUri = "https://" + strRedirectUri.Substring(nPos, strRedirectUri.IndexOf("/", nPos) - nPos + 1);
                            strRedirectUri = strPostLogoutRedirectUri;
                            if (strRedirectUri.Contains("localhost"))
                            {
                                strRedirectUri = strPostLogoutRedirectUri + ".auth/login/aad/callback";
                            }
                        }
                        else
                        {
                            strRedirectUri = "https://YOURSITE.com/";
                            strPostLogoutRedirectUri = "https://YOURSITE.com/";
                        }
                        context.ProtocolMessage.RedirectUri = strRedirectUri;
                        context.ProtocolMessage.PostLogoutRedirectUri = strPostLogoutRedirectUri;
                        return System.Threading.Tasks.Task.FromResult(0);
                    }
                }
            }
            );

        // This makes any middleware defined above this line run before the Authorization rule is applied in web.config
        app.UseStageMarker(PipelineStage.Authenticate);
    }

    private static string EnsureTrailingSlash(string value)
    {
        if (value == null)
        {
            value = string.Empty;
        }

        if (!value.EndsWith("/", StringComparison.Ordinal))
        {
            return value + "/";
        }

        return value;
    }
Eduardo
  • 78
  • 3