4

I am trying to set the redirect_uri in Azure B2C. I have a language field in the Url like this:

https://mydomain/de-de/projects
https://mydomain/en-us/projects
https://mydomain/sv-se/projects 
https://mydomain/ar-sa/projects
...

and to be correctly redirected, I have to add all the possibilities to the B2C Reply URLs and I am only limited to 20 max.

Is there a way to add variables to the redirect_uri? Something like:

https://mydomain/:lang/projects

where ":lang" is a variable the could take any value. enter image description here

////////////////////////////////////

Solution

The tricky solution was to manipulate the state and inject it with the returned URL due to the fact that it will be sent back after the login/signup response. createLoginUrl() method:

let url = that.loginUrl
                        + '?response_type='
                        + response_type
                        + '&client_id='
                        + encodeURIComponent(that.clientId)
                        + '&state='
                        + encodeURIComponent((state) + 'url'  + returnedUrl)
                        + '&redirect_uri='
                        + encodeURIComponent(window.location.origin)
                        + '&scope='
                        + encodeURIComponent(that.scope);

so here I split the state with 'url' word so I can read it again after the response came.

encodeURIComponent((state) + 'url' + returnedUrl)

An important details redirect_uri, it should be the same origin:

'&redirect_uri=' + encodeURIComponent(window.location.origin)

and this URL should be added to the returned URL in Azure B2C application.

Now I can split it again in tryLogin() method:

const statePartsWithUrl = (parts['state'] + '').split('url');
window.location.href = statePartsWithUrl[1];

and it works perfectly.

////-------------------------------------

Edit : 1.2.2019

const statePartsWithUrl = (parts['state'] + '').split('url');
let state = '';
let returnedUrl = '';
if (statePartsWithUrl != null) {
  state = statePartsWithUrl[0];
  returnedUrl = statePartsWithUrl[1];
}

Here is the splitting of the state to read the information from it in method tryLogin(options)

Samy Sammour
  • 2,298
  • 2
  • 31
  • 66
  • Did you do this in a Javascript method? I have been trying to find a way to access the "state" variable via the OpenIdConnectAuthenticationOptions and have found no way to add in information that I could then use to apply different redirects and such. @SamySammour – ewahner Jan 30 '19 at 16:32
  • Add the information to the state as I mentioned above with a splitter or something. + '&state=' + encodeURIComponent((state) + 'url' + ([your_data])) – Samy Sammour Feb 01 '19 at 14:19
  • the data you can split it later and read it from the state – Samy Sammour Feb 01 '19 at 14:20
  • please see my new edit – Samy Sammour Feb 01 '19 at 14:23

1 Answers1

3

Yeah so as you found out, you can't currently add wildcards to reply URLs in B2C.

This may be due to security concerns defined in the OAuth 2.0 Threat Model and Security Considerations RFC. In it, the suggested counter-measure against Open Redirect Attacks is to have the client register the full redirect URI.

There is also no way to create apps programmatically: https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/19975480-programmatically-register-b2c-applications.

So sadly the manual way is the only way at the moment. But be sure to go upvote the feature request on User Voice.

I actually even tried to manually edit an app via Graph Explorer:

{
    "odata.error": {
        "code": "Request_BadRequest",
        "message": {
            "lang": "en",
            "value": "Updates to converged applications are not allowed in this version."
        },
        "date": "2018-01-08T12:00:00",
        "requestId": "208e7159-d459-42ec-8bb7-000000000000",
        "values": null
    }
}

As you suggested in the comments, one way to work around this problem would be to use a single static redirect URI and keep the language/culture in the state/a cookie, and then do the redirect to the language-specific version after the user is returned to the app.

Community
  • 1
  • 1
juunas
  • 54,244
  • 13
  • 113
  • 149
  • I guess the solution would be is to set a static return_uri (which is the domain) and send the actual returned Url within the state as a json object and then redirect manually when the response came. – Samy Sammour Jan 08 '18 at 17:43
  • Oh hey that's a pretty good idea! You could also use a cookie for that :) I'll add that to the answer. – juunas Jan 08 '18 at 17:44
  • 1
    I guess the cookie is not required in this case because the state will be sent back completely with the Url. More work but achievable! :) – Samy Sammour Jan 08 '18 at 17:51
  • 1
    Round-tripping the return URL, which doesn't have to be registered with Azure AD B2C, in the state parameter is the common approach. See [this answer](https://stackoverflow.com/questions/47520604/why-is-redirect-url-fully-qualified-in-azure-ad-b2c/47527533#47527533) for more info. – Chris Padgett Jan 08 '18 at 21:22
  • 1
    Hello @juunas, I added the solution up there with the question. If you are interested you can take a look. Cheers! – Samy Sammour Feb 06 '18 at 16:13