Force re-authentication using onelogin as SP and IDP - onelogin

I'm trying to force a re-authentication using SAML and Onelogin as the IDP, and the onelogin java lib for the SP.
For certain functions I would like to trigger a re-authentication, before the user can proceed.
First time user logs in to my application he must enter his credentials. After that he is logged in. But when I try to send an AuthnRequest, the user is immediately redirected back to my application without having to enter his credentials again.
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ONELOGIN_xxx" Version="2.0" IssueInstant="2019-11-07T12:31:09Z" ForceAuthn="true" Destination="https://myapp.onelogin.com/client/apps/select/xxx" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="https://local.my.app:8443">
<saml:Issuer>local.my.app</saml:Issuer>
<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" AllowCreate="true" />
<samlp:RequestedAuthnContext Comparison="exact">
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
</samlp:RequestedAuthnContext>
</samlp:AuthnRequest>
How can I force the user to re-enter his credentials again?

Try including ForceAuthn="true" in the SAML request.

Related

Azure AD B2C Custom policy SAML token lifetime & session timeout

I configured a custom b2c policy for the sign-up/sign-in flow that uses SAML for token exchange.
I would like to understand how to control the token lifetime (SAML) and session duration.
The session duration should be 4 hours, to prevent the user from continuing to re-enter credentials I would like to be able to configure an idle timeout so that the session is disconnected if there is no interaction.
Also I would like if the user closes the browser without logging out, when reopened it will prompt for credentials
Is all of this possible? At the moment I'm not using offline_access scope on app registration.
offline_access scope app registration not enabled
At the moment I have only tried putting this in my RP file:
<RelyingParty>
<DefaultUserJourney ReferenceId="SignUpOrSignInMFAOption" />
<UserJourneyBehaviors>
<SingleSignOn Scope="Application" />
<SessionExpiryType>Rolling</SessionExpiryType>
<SessionExpiryInSeconds>900</SessionExpiryInSeconds>
</UserJourneyBehaviors>
<TechnicalProfile Id="PolicyProfile">
<DisplayName>PolicyProfile</DisplayName>
<Protocol Name="SAML2" />
PFB answers to your ask as follows:
Control the token lifetime (SAML) and session duration
To define a session duration for SAML you could use "TokenLifeTimeInSeconds" in Saml2AssertionIssuer technical profile metadata.
As per https://learn.microsoft.com/en-us/azure/active-directory-b2c/saml-issuer-technical-profile#metadata TokenLifeTimeInSeconds specifies the life of the SAML Assertion. This value is in seconds from the NotBefore value referenced above. The default value is 300 seconds (5 Min).
I would like if the user closed the browser without logging out, when reopened it will prompt for credentials
This could be achieved for local accounts only by removing /excluding Keep me signed in (KMSI) claim, when you enable the feature, users can opt to stay signed in, so the session remains active after they close the browser. The reference sample could be found https://github.com/azure-ad-b2c/unit-tests/blob/main/session/Session_KeepAliveInDays.xml
Also, the SAML IDP metadata should have ForceAuthN set to true
Passes the ForceAuthN value in the SAML authentication request to determine if the external SAML IDP will be forced to prompt the user for authentication. By default, Azure AD B2C sets the ForceAuthN value to false on initial login. If the session is then reset (for example by using the prompt=login in OIDC) then the ForceAuthN value will be set to true. Setting the metadata item as shown below will force the value for all requests to the external IDP. Possible values: true or false. Ref: https://learn.microsoft.com/en-us/azure/active-directory-b2c/saml-identity-provider-technical-profile#metadata
Please do let me know if you have any further queries for me in the comments section.
Thanks

Azure B2C Custom Policies local account KMSI doesn't keep me signed in

I implemented the steps in the example - all worked as expect to this point - and then I followed the instructions to enable KMSI.
When testing Identity Experience Framework->Custom Policies->B2C_1A_signup_signin ->Run , I can switch on the tickbox "Keep me signed in" when signing in. However, I close this window (or keep it open for that matter), Run the custom policy again and asks me to sign in again ("Keep me signed in" shows unticked).
I have triple checked the changes in the tutorial and example and can't see any difference (other than in the example I don't have LoadURI and RecoveryURI.
I note I have not made changes as per ContentDefinitions and only followed the instructions in enable KMSI because I didn't think that was a requirement in the tutorial.
Please give me some guidance what may be wrong. Thank you for your help
You are using a wrong method to test the KMSI feature.
If you "Run the custom policy again", it will always ask you to reenter your credential, which is by-design.
You should follow the steps of Test your policy.
You can close the window after you sign in for the first time.
And then follow the step 4, 5 and 6:
Go back to the Azure portal. Go to the policy page, and then select Copy to copy the sign-in URL.
In the browser address bar, remove the &prompt=login query string parameter, which forces the user to enter their credentials on that
request.
In the browser, click Go. Now Azure AD B2C will issue an access token without prompting you to sign-in again.
UPDATE:
You don't need to replace the SignUpOrSignin.xml and TrustFrameworkExtensions.xml. Just refer to my changes:
Add the following code snippet into the BuildingBlocks element in TrustFrameworkExtensions.xml.
<ContentDefinitions>
<ContentDefinition Id="api.signuporsignin">
<LoadUri>~/tenant/default/unified.cshtml</LoadUri>
<RecoveryUri>~/common/default_page_error.html</RecoveryUri>
<DataUri>urn:com:microsoft:aad:b2c:elements:unifiedssp:1.1.0</DataUri>
<Metadata>
<Item Key="DisplayName">Signin and Signup</Item>
</Metadata>
</ContentDefinition>
</ContentDefinitions>
And then add the following node as a child of the element. It must be located immediately after <DefaultUserJourney ReferenceId="User journey Id" />.
<UserJourneyBehaviors>
<SingleSignOn Scope="Tenant" KeepAliveInDays="30" />
<SessionExpiryType>Absolute</SessionExpiryType>
<SessionExpiryInSeconds>1200</SessionExpiryInSeconds>
</UserJourneyBehaviors>
These are all the changes need to be made.
You don't need to remove &prompt=login in the files. Please see my screenshot above. After you copy the sign-in URL, it will be like this:
https://**.b2clogin.com/**.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1A_SignUpOrSignIn&client_id=**&nonce=defaultNonce&redirect_uri=https%3A%2F%2Fjwt.ms&scope=openid&response_type=id_token&prompt=login
Just remove the &prompt=login at the end of the URL and access it in a new window.

Azure API Management: authorization with Oauth2 401 gives "Unauthorized. Access token is missing or invalid."

I have a few APIs (Logic Apps, Functions) that I want to expose through Azure API Management.
They work fine, so I decided to add OAuth2 autorization.
I followed step by step https://learn.microsoft.com/fr-fr/azure/api-management/api-management-howto-protect-backend-with-aad:
Register an application (backend-app) in Azure AD to represent the API.
Register another application (client-app) in Azure AD to represent a client application that needs to call the API.
In Azure AD, grant permissions to allow the client-app to call the backend-app.
Configure the Developer Console to call the API using OAuth 2.0 user authorization.
Add the validate-jwt policy to validate the OAuth token for every incoming request.
Also use Postman to test
Everything works until the "validate-jwt" policy step.
When I add it, I get a "401 - Unauthorized. Access token is missing or invalid."
I can get the token, in Developer Console and Postman, but as soon as I do the API call... 401!
When I used jwt.ms to check the content of the token, I noticed that the aud param has nothing to do with the backend Application ID.
The value in the token is "00000003-0000-0000-c000-000000000000", whereas the backend app ID is like "16caXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXc0".
I'm running out of ideas and need the help of some Azure gurus out there!
Help would be very much appreciated...
Here below the inbound policy as per the MS doc:
<policies>
<inbound>
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<openid-config url="https://login.microsoftonline.com/MY_AD_TENANT_ID/.well-known/openid-configuration" />
<required-claims>
<claim name="aud">
<value>MY8BACKEND_APP_ID_GUID</value>
</claim>
</required-claims>
</validate-jwt>
</inbound>
<backend>
<forward-request />
</backend>
<outbound />
<on-error />
</policies>
Screen cap of the Postman screen where I get the token (this works, but then when I send the request --> 401)
Screen cap of aud param in jwt.ms
I had some problems with validating Azure AD tokens a couple of years back - see my write up.
I suspect the problem is the nonce in the JWT header.
You're not really required to check value of aud parameter. You could remove required-claims alltogether, this way token presence and signature would still be validated. If you want to make sure that token was issued for your app, just find the claim that contains app id and use it in name="..." to match against your app id value.
if using v2 version endpoint, go to -> azure ad -> app registration -> select backend-app -> manifest -> update property "accessTokenAcceptedVersion": 2,"

How to get the username from ADFS for a claims provider

We have written a custom claims provider for ADFS. It's all working fine: you enter your username and credentials in our login page, and it authenticates you to ADFS. There's just one annoying omission: if you come from Office 365 portal and enter your email address, you get redirected to ADFS, then to our login page... but without the email address. You have to re-enter it before you can login.
I can't see anyway to request that ADFS forwards the email address as part of the SAML request, or to check if there is already an email address associated with the SAML request.
Regards
Robin Withey
I think you need to look into the UID and Mail attributes of the SAML response...
<saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">test#example.com</saml:AttributeValue>
</saml:Attribute>

The provided anti-forgery token was meant for user "UserName", but the current user is ""

When I am login with user's credential, first time no error while login to application,
but when I logoff and again login with other user's credential got an error
The provided anti-forgery token was meant for user "UserName", but the current user is "".
I am implementing AntiForgoryToken and IPrincipal with asp.net mvc 5
I tried :
AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in Application_Start()
I already refered this link When attempt logoff, The provided anti-forgery token was meant for user "XXXX", but the current user is ""
How can I fix this error ?
Thanks in advance.
I found my IIS instance had both Anonymous and Windows authentication enabled which was causing this exception for my application
Authentication Settings both enabled
This setting seems to be the cause of this exception. It seems that the ValidateAntiForgeryToken action filter was using the current user populated with an empty string in the Anon authentication and then attempting to match it against the token which was populated using Win authentication.
By turning off either Windows or Anonymous authentication (for my application I switched off Anon authentication,) the tokens now match up.
Authentication Settings one enabled
This setting can be altered in IIS manager or in the web.config file like so
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
You don't really need to check for the antiforgery token on the post method of your login.
Antiforgery tokens provide protection from CSRF attacks. A CSRF attack happens when a malicious script/link posts an HTTP request on your behalf without your knowledge or consent. When an antiforgery token is embedded on your page, the server can check for this token when it receives the request to verify that the request indeed came from the page. A request from a malicious script or link will not have the token and will fail.
So, all other post actions that you want to protect should be decorated them with the [Authorize] and [ValidateAntiForgeryToken] attributes. The login post method, however, doesn't need either of these attributes.
Update: It is really needed. See answer in Stephen Muecke's comment.

Resources