Microsoft-authentication-library-for-js: redirectUri getting ignored

Created on 7 Jun 2018  路  26Comments  路  Source: AzureAD/microsoft-authentication-library-for-js

I include redirectUri when I invoke msal.js but after logging in on Azure AD B2C login page, user gets redirected to the page he/she came from, instead of the redirectUri I specify. Why is this happening?

Here's my code

<script>
   var instance = 'https://login.microsoftonline.com/tfp/';
   var tenant = 'myazureadb2ctenant.onmicrosoft.com';
   var signInPolicy = 'B2C_1_SignUp_SignIn';
   var applicationId = 'my-application-id';
   var scopes = ['https://myazureadb2ctenant.onmicrosoft.com/webclient/readaccess'];
   var redirectUri = 'https://example.com/member';
   var authority = `${instance}${tenant}/${signInPolicy}`;

   var clientApplication = new Msal.UserAgentApplication(
       applicationId,
       authority,
       function (errorDescription, token, error, tokenType) {
          // Handle error
       },
       {
            redirectUri: redirectUri
       });

       var mySignInFunction() {
              clientApplication.loginRedirect(scopes);
       };
</script>

All 26 comments

@imsam67 - In MSAL, by default the user is redirected to the page where she/he started. This can be set to false using this flag navigateToLoginRequestUrl. You can pass this as an optional parameter for UserAgentApplication constructor.

var clientApplication = new Msal.UserAgentApplication(
       applicationId,
       authority,
       function (errorDescription, token, error, tokenType) {
          // Handle error
       },
       {
            redirectUri: redirectUri,
           navigateToLoginRequestUrl:false
       });

       var mySignInFunction() {
              clientApplication.loginRedirect(scopes);
       };

@nehaagrawal Just added navigateToLoginRequestUrl:false as you suggested but I'm still getting redirected to where I came from and not the redirectUri. I'm using version msal v0.1.6 2018-05-21. Any idea why the redirectUri is getting ignored?

Here's a screen shot of the clientApplication object right before invoking clientApplication.loginRedirect(scopes);. As you can see both the navigateToLoginRequestUrl: false and redirectUri: http://localhost:49065/member are set in the object but after login, I'm still sent back to http://localhost:49065 which is where I invoke the sign in process. I should be sent back to http://localhost:49065/member.

capture

@imsam67 I just tested this in our sample app and it works, Can you please confirm 2 things

  1. do you see the id_token in the url on this path http://localhost:49065/member#id_token...?
  2. can you please put a breakpoint at this code in userAgentApplication.ts and check what is the value of window.location.href in else block.
  if (self._navigateToLoginRequestUrl) {
            tokenReceivedCallback = null;
            self._cacheStorage.setItem(Constants.urlHash, hash);
            saveToken = false;
            if (window.parent === window && !isPopup) {
                window.location.href = self._cacheStorage.getItem(Constants.loginRequest);
            }
            return;
        }
        else {
            tokenReceivedCallback = self._tokenReceivedCallback;
            window.location.hash = '';
        }

@nehaagrawal Actually, I don't see id_token in the path. I think you're referring to what's in the path once I log in through the Azure AD B2C login page. Here's the first part of what I'm seeing:
http://localhost:49065/member#state=c78021f1-e91b-490c-a6eb-f361d0b81594&client_info=eyJ1aWQiOiIzNzM3MT...

The token is obtained though. If I manually type http://localhost:49065/member, I can actually go into the protected part of my app.

I want to clarify something. Maybe I'm handling something wrong. I'm invoking the login from a static landing page that is not part of my SPA. The landing page is at http://localhost:49065 and after login, I want to send user to http://localhost:49065/member. Currently, user is redirected back to where he came from which is the landing page. I thought I could use the redirectUri to send the user to http://localhost:49065/member which is where the SPA is. What am I missing here?

Implementing this has been painful to put it mildly. Looks like it's not just my experience!!! How can one disagree with this? https://www.azurefromthetrenches.com/azure-ad-b2c-a-painful-journey-goodbye-for-now/

@imsam67 What url do you have in the configured "Application" in the B2C setup for Reply Url? I assume it is http://localhost:49065 right? So when authentication completes, it comes back to your landing page. Perhaps what you are looking for is to have both urls set up in the the B2C config as Reply Urls. B2C will not redirect to a url not in the configured reply list. One thing to note here, redirectUrl is meant to drive what url the callback is made to with the tokens, NOT where to navigate the browser upon successful login. What you probably want is to have the landing page accept the callback and redirect to /member upon success yourself. Alternatively, you can have the member page accept the callback but that seems like it would be odd in the case of auth failure.

@4deeptech The URL configured under application at B2C portal is http://localhost:49065/member. That's also the redirectUri configured on the client side on the landing page. That's why I'm so confused that I keep getting sent back to the landing page at http://localhost:49065. I've been banging my head against the wall on this.

Currently the only solution I have is to send the user to http://localhost:49065/member from the landing page and let msal.js do another redirect to the login page for Azure AD B2C. This is absolutely terrible user experience but I haven't been able to achieve my goal any other way.

user gets redirected to the page he/she came from, instead of the redirectUri I specify. Why is this happening?

It's a pretty cool feature IMO. Unfortunately, it is not well documented (at least to my knowledge).

It helps solve the "I have hundreds or thousands of page URLs" problem. Then you don't have to register ever unique URL in your app.

Some related details are here: Why is Redirect URL Fully Qualified in Azure AD B2C?

Any idea why the redirectUri is getting ignored?

I would turn on Preserve Log in Chrome debug tools

image

Then you can see the URL(s) your app navigated to. That might help diagnosis the issue.

I troubleshot the opposite of your problem w/ a fellow dev the other day. Turns out our AuthentactionGuard was causing problems and seeing URL the app navigated to help identify it.

I'm invoking the login from a static landing page that is not part of my SPA

Are you using MSAL.js to invoke the login?

I'm invoking the login using the code I included in the original post here. Initially, I was using an older version of msal.js but since my post here, I updated it to the latest version which I believe is 0.1.6.

I'm still not clear if I'm even able to do what I'm trying to accomplish. Can I invoke the login from a static landing page which is NOT part of my SPA and after the login have the user sent to the entry point URL for my SPA?

In my case, the landing page is at http://localhost:49065 and once the user logs in, I'd like the user to be sent to http://localhost:49065/member.

I have http://localhost:49065/member set under Application on Azure AD B2C configuration on Azure Portal.

Is this even possible OR will msal.js always return the user where he/she came from?

Can I invoke the login from a static landing page which is NOT part of my SPA and after the login have the user sent to the entry point URL for my SPA?

I can't think of any reason why that wouldn't work. When using MSAL.js, it using session or local storage for everything, so provided you have the same config and construction parameters of UserAgentApplication it wouldn't know that you are in the SPA or not.

Is this even possible OR will msal.js always return the user where he/she came from?

No, MSAL.js will not always return the user when they came from. All depends upon navigateToLoginRequestUrl. That I can definitively state as we use it in our app.

Do you have multiple places you're creating UserAgentApplication?

FYI, navigateToLoginRequestUrl is handled upon returning to your app: https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/319

@spottedmahn Someone who's been helping with this on StackOverflow told me that I might be able to set my returnUri -- NOT redirectUri in sessionStorage but I haven't had any success with it.

Here's what he told me on SO: https://stackoverflow.com/questions/50684291/invoking-msal-sign-in-from-static-html-page/50730242?noredirect=1#comment88476086_50730242

@spottedmahn Currently, I have one in the SPA app so that if anyone goes to http://localhost:49065/member directly, they'll get sent to the login page on Azure. I also have a UserAgentApplication in the static landing page -- see my code above in original post. That's pretty much it.

Someone who's been helping with this on StackOverflow told me that I might be able to set my returnUri -- NOT redirectUri in sessionStorage but I haven't had any success with it.

You don't need to reach into storage to control this. Generally speaking, Chris is amazing and knows his stuff inside and out but he apparently doesn't know about this relatively new parameter. Reference release 0.1.5

FYI, the code that controls the redirect behavior is here.

It is pretty simple. If navigateToLoginRequestUrl true then send the user back othewise don't.

@spottedmahn I have tears in my eyes!!!! It's working!!!!

@spottedmahn I can't thank you enough!!!!

Actually, I'm not even sure if I'm doing this right but it's working. I'm simply doing a redirect in the callback function.

Once the user logs in and we obtain a token, the user is sent back to my static landing page, into the callback function. In there, I can simply do a redirect.

Anything wrong with that approach? I set navigateToLoginRequestUrl to both true and false and in both cases, I end up in the callback function so I can do a redirect.

It's too easy so this approach may be flawed!!!

@imsam67 The navigateToLoginRequestUrl just controls the final redirect back to your loginStartPage. The callback function will be called in both cases regardless. I don't see anything wrong with the approach suggested by @spottedmahn .
Please let us know if you have further questions and feel free to close this issue if your question is answered.

I could use some clarity on what loginStartPage is.

Is it the page where the user initiated the login process? Or the redirectUri set on Azure portal?

Also, am I understanding this correctly that where I want to send the user to after the login will always be handled in the callback function?

@spottedmahn I have tears in my eyes!!!! It's working!!!!

That's great!! 馃挜

I'm simply doing a redirect in the callback function.

That certainly works but you shouldn't need to do that. Something else must be going on...

I could use some clarity on what loginStartPage is.
Is it the page where the user initiated the login process?

Yes. Reference: The code that sets it for loginRedirect

It's weired that callback and redirectUri not working together.
If I put redirectUri in config, I can't get benefit of using callback.
Even I can't get tokens at my localstorage.

Was this page helpful?
0 / 5 - 0 ratings