Extra query parameters - azure-ad-b2c

It is possible to pass extra query parameters from the web application that calls the B2C policy.
With MSAL:
AuthenticationParameters.extraQueryParameters
{
extraQueryParameters: { ['utm_source']: window.location.origin },
}
This will add "&utm_source=something.com" in the URL
mytenant.b2clogin.com/mytenant.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1A_signup_signin&utm_source=something.com&.....
My problem is that as soon as I jump to a second page, or click on the Sign Up link, you completely loose all of these extra query parameters.
i.e You click on SignUp, the url is now
mytenant.b2clogin.com/mytenant.onmicrosoft.com/B2C_1A_signup_signin/api/CombinedSigninAndSignup/unified?local=signup&csrf_token=123456&tx=StateProperties=123456&p=B2C_1A_signup_signin
How can I keep these extra query params?
How can I also keep these params when you go to a Social IDP then back on the social confirmation page?

Resolve the query parameters in the initial page. Then it doesn’t matter what the user does next.

Related

Azure AD B2C with MSAL change redirect url on success

I have a React app which uses MSAL msal-react v1.3.1. I am using loginRedirect method to redirect a predefined user flow configured in Azure B2C for password reset. The current behaviour is that when the password reset is complete it redirects back to the page that first invoked the redirect to AD B2C once it has completed successfully.
Is there a way to change the redirect url when the flow has completed to something like below?
instance.loginRedirect({
authority: `${config.authentication.authority}/${config.authentication.flow.register}`,
redirectUri: window.location.href + '?success=true'
});
I have tried to set the redirectUri and postLoginRedirectUri which don't appear to change the outcome.
There appears to be a restriction on the redirectUrl as described here.
The redirect url must be registered with the application and cannot contain wildcards or query string parameters.
What I had to do in this situation was set the navigateToLoginRequestUrl to false where you set up your msal. Example of someone's code with the navigateToLoginRequestUrl option: https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/3818
Then maybe you could use the state option to pass any information you want to the return URL instead of a query parameter on returnURL. But I don't quite see the point here.
instance.loginRedirect({
authority: `${config.authentication.authority}/${config.authentication.flow.register}`,
redirectUri: window.location.href,
state: 'success'
});

Cancelling new user signup in Azure AD B2C redirects to sites home page, produces "AuthorizationFailed" error

I have a Blazor Hosted WASM application, and am using Azure AD-B2C to secure it. If a user who is not logged in tries to access any site on the page, they are directed to our b2c login page, as they should be, and if they supply a good username and password they are allowed to view the site. So far so good. However, if the user clicks on "Sign up now", and then cancels the signup process instead of providing a new username, password, and e-mail address, then they are redirected to the site's landing page (as if they had provided a good username and password), which fails to redirect them back to the b2c login page and produces a console message reading "info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user"
The documentation suggests that I access the app's manifest and set the allowPublicClient attribute to null or true to address this problem. I have done this, and the problem persists. Why isn't the user being redirected back to the B2C login page in this case, when they normally would be if they try to access any page on the site (including this landing page) in other cases?
When the user cancels and get redirected back to the landing page, it returns an specific error code in the url (eg: AADB2C90118) in the return redirect url (In some cases it only flashes quickly because Angular removes the query string after the redirect).
You need to listen to this and handle it. You can handle it manually by parsing the return url but if you use msal.js on client side you can listen to this and start the reset password flow.
this.broadcastService.subscribe("msal:loginFailure", (error) => {
console.warn("msal:loginFailure", error);
// Check for forgot password error
// Learn more about AAD error codes at https://learn.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes
if (error.errorMessage.indexOf("AADB2C90118") > -1) {
alreadyRedirecting = true;
this.msalAuthService.loginRedirect(
b2cPolicies.authorities.resetPassword
);
}
});
The above example is for when the user clicks on forgot password link and get redirected back, so you will need to find the error code that applies to you.

Azure Logic App Request Trigger authorization

I have a Logic App with an HTTP initial trigger that is all set up:
When I make the POST to the URL that is given to me (looks like https://___.azure.com/workflows/___/triggers/manual/paths/invoke?____), I get back:
{"error": {
"code":"AuthorizationFailed",
"message":"The authentication credentials are not valid."
}}
For this case, I need to accept anonymous calls.
Where in the Azure Portal do I setup the permissions for this?
The closest I've found is the "Access Control Configuration", and it is set like this:
Logic Apps does not allow anonymous calls, you are required to provide the SAS key, which is provided in Url generated on the request card.
Found the issue. My client-side code was appending a parameter to the URL without realizing the URL already had query parameters. As such, it was adding to the last parameter rather than adding a new parameter. With that fixed, the call works.
Yes, the URL that will be present at the callbacK URL while creating should work, Does your URL has SP, sv and sig query paramemters?

chrome.identity.LaunchWebAuthFlow: How to implement logout in a web app using oauth2

I am working on some client side web app like a chrome extension that needs access to outlook mail and calendar. I followed the instruction on https://dev.outlook.com/RestGettingStarted and successfully got access and refresh tokens to retrieve data.
However, I cannot find any way of implementing "logout". The basic idea is to let user sign out and login with a different outlook account. In order to do that, I removed cached tokens, requested access tokens in interactive mode. The login window did pop out, but it took any valid email address, didn't let me input password and finally returned tokens for previous account. So I was not able to really use a different account until the old token expired.
Can anyone please tell me if it is possible to send a request to revoke the tokens so people can use a different account? Thanks!
=========================================================
Update:
Actually it is the fault of chrome.identity api. I used chrome.identity.LaunchWebAuthFlow to init the auth flow. It caches user's identity but no way to remove it. So we cannot really "logout" if using this api.
I used two logouts via launchWebAuthFlow - first I called the logout link to my app, then secondly, I called the logout link to Google.
var options = {
'interactive': false,
'url': 'https://localhost:44344/Account/Logout'
}
chrome.identity.launchWebAuthFlow(options, function(redirectUri) {});
options = {
'interactive': false,
'url': 'https://accounts.google.com/logout'
}
chrome.identity.launchWebAuthFlow(options, function(redirectUri) {});

Azure ACS custom Identity Provider Single SignOut

I'm implementing my own identity provider based on Thinktecture code. Here is a strange behaviour of Azure ACS while using a single sign-out feature, it differ for google/live and for my own identity provider.
URL for sign-out (realm is really same as a site name):
mysite.accesscontrol.windows.net/v2/wsfederation?wa=wsignout1.0&wreply=http%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f&wtrealm=http%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f
Here is a pseudo-code for logout:
//clear FedAuth cookies
FormsAuthentication.SignOut();
FederatedAuthentication.WSFederationAuthenticationModule.SignOut(true);
//call Single SignOut
var signoutRequestMessage = new SignOutRequestMessage(new Uri(signOutUrl));
return Redirect(signoutRequestMessage.WriteQueryString());
Here is sample flow (i'm using private browsing plus Fiddler to see everything):
1) I'm logging into my application with google account.
2) click a logout, in result i get a page on ACS with a this code:
function on_completion()
{window.location = 'http://localhost/Administration.Frontend.Web/';}
<iframe src="https://www.google.com/accounts/Logout" style="visibility: hidden"">/iframe>
<iframe src="http://localhost/Administration.Frontend.Web/?wa=wsignoutcleanup1.0" style="visibility: hidden"></iframe>
Result: i'm logged out from my application and google.
3) Log to my identity provider, click logout, redirected to same URL on ACS as on previous step but now i get 302 result with redirecting to
https://localhost/IdentityProvider/issue/wsfed?wa=wsignout1.0&wreply=https%3a%2f%2fmysite.accesscontrol.windows.net%2fv2%2fwsfederation%3fredirectUrl%3dhttp%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f
Result: i'm logged out from my application and my identity provider.
4) try to use google again, sucessfully login by entering credential, but logout if failed. I'm logged out from application but not logged from google. And also i see that i don't get page with iframe but instead ACS again try to redirect me to
https://localhost/IdentityProvider/issue/wsfed?wa=wsignout1.0
(and then back to mysite.accesscontrol.windows.net and finally to my application)
Two main question:
Why calling ACS logout give me iframe page with additional
wa=wsignoutcleanup1.0 for google/live but 302 redirect to my
identity provider, may be i miss something in
FederationMetadata.xml?
It looks like ACS after step 3 don't
understand that i successfully logged out from my identity provider
and from this moment try to do it again and again, how to tell them
to stop it?
Here is what you have to do.
First of all, when working with federated authentication always use HTTPS! Sometime protocol negotiations will fail just because it is plain HTTP. Sometimes browsers will block non-secure traffic, which is crucial for the sign-out process. So, always use HTTPS!
Now, to implement the form of single sign out you want you have do some more work.
Your URL for sign-out:
mysite.accesscontrol.windows.net/v2/wsfederation?wa=wsignout1.0&wreply=http%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f&wtrealm=http%3a%2f%2flocalhost%2fAdministration.Frontend.Web%2f
Do not use it as a parameter to construct SignOutRequestMessage. Use it to directly return Redirect(signOutUrl)!
You have to implement sign-out in two major places!
First place is your general logOff action method (given you are using MVC) Something similar to what you already have but with an important change:
FormsAuthentication.SignOut();
var signoutProtocolLocation = "https://[your_acs_namespace].accesscontrol.windows.net:443/v2/wsfederation?wa=wsignout1.0&wtrealm=[realm]&wreply=[reply]";
FederatedAuthentication.WSFederationAuthenticationModule.SignOut(signoutProtocolLocation);
Note that here I use the overload with string paramer` to redirect result to ACS SSO location!
Now that very ACS SSO location will generate the above mentioned HTML page with JS and couple of iframe elements. One of them will be something like:
<iframe src="http://localhost/Administration.Frontend.Web/?wa=wsignoutcleanup1.0" style="visibility: hidden"></iframe>
Now that particular location http://localhost/Administration.Frontend.Web/?wa=wsignoutcleanup1.0 is the second place in your code where you have implement the SSO. This request must not redirect to a login page, but must instead process correctly and return 200 or 301 response (which in turn will return 200!)! For the sake of simplicity I will only paste the code used here:
if(Request.QueryString.AllKeys.Contains("wa")
&& Request.QueryString["wa"].Equals("wsignoutcleanup1.0"))
{
FederatedAuthentication.WSFederationAuthenticationModule.SignOut(true);
return RedirectToAction("Index");
}
It is really important that you only call the SignOut(true) overload with true when it is request for wsignoutcleanup action. And not when you do general log-off of users.
Please try all mentioned changes and let me know if it solves your issue!

Resources