sanity-io / sanity

Sanity Studio – Rapidly configure content workspaces powered by structured content
https://www.sanity.io
MIT License
5.28k stars 426 forks source link

SSO Windows Hello problem - login only accepts username / password login #7472

Closed EECOLOR closed 1 month ago

EECOLOR commented 2 months ago

The SAML SSO connection triggers the following error on Microsoft machines:

Authentication method 'X509, MultiFactor, X509Device' by which the user authenticated with the service doesn't match requested authentication method 'Password, ProtectedTransport'.

This affects a lot of our customers that use Windows Hello to authenticate.

Please adjust the SAML authentication request to include those methods. The endpoint sends the following SAML request:

<?xml version="1.0"?>
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_xyz" Version="2.0" IssueInstant="2024-09-06T15:44:27.270Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Destination="https://login.microsoftonline.com/xyz/saml2" AssertionConsumerServiceURL="https://api.sanity.io/v2021-10-01/auth/saml/callback/xyz">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://sso.sanity.io/saml/xyz</saml:Issuer> 
 <samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" AllowCreate="true"/>
  <samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact"> 
   <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
  </samlp:RequestedAuthnContext>
</samlp:AuthnRequest>

The Sanity endpoint has this payload in the redirect at https://api.sanity.io/v2021-10-01/auth/saml/login/xyz

EECOLOR commented 2 months ago

Information from Microsoft: https://learn.microsoft.com/en-us/troubleshoot/azure/entra/entra-id/app-integration/error-code-AADSTS75011-auth-method-mismatch

plsrd commented 1 month ago

Thanks for reporting! We've implemented a fix that should allow you to use Windows Hello properly.

EECOLOR commented 1 month ago

@plsrd The service still redirects with the same SAMLRequest query string:

<?xml version="1.0"?>
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_..." Version="2.0" IssueInstant="2024-10-04T14:20:06.230Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Destination="https://login.microsoftonline.com/.../saml2" AssertionConsumerServiceURL="https://api.sanity.io/v2021-10-01/auth/saml/callback/...">
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://sso.sanity.io/saml/...</saml:Issuer>
  <samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" AllowCreate="true"/>
  <samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact"> 
    <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
      urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
    </saml:AuthnContextClassRef>
  </samlp:RequestedAuthnContext>
</samlp:AuthnRequest>

From the Microsoft link:

Cause The RequestedAuthnContext is in the SAML request. This means the app is expecting the AuthnContext specified by the AuthnContextClassRef. However, the user has already authenticated prior to access the application and the AuthnContext (authentication method) used for that previous authentication is different from the one being requested.

... The AuthnContextClassRef will be urn:federation:authentication:windows. Microsoft Entra ID won't perform a fresh authentication request, it will use the authentication context that was passed-through it by the IdP (ADFS or any other federation service in this case). Therefore, there will be a mismatch if the app requests other than urn:federation:authentication:windows. Another scenario is when MultiFactor was used: X509, MultiFactor.

Resolution RequestedAuthnContext is an optional value. If possible, ask the application if the value could be removed.

Another option is to make sure that the RequestedAuthnContext value will be honored. This is done by requesting a fresh authentication. By doing this, when the SAML request is processed, a fresh authentication is done and AuthnContext is honored. In order to request a Fresh Authentication, the SAML request must contain the value, forceAuthn="true".

EECOLOR commented 1 month ago

image

EECOLOR commented 1 month ago

In Slack Darius notified my of a change, I can confirm that the payload has changed. Now waiting for the end user to test. Will report the findings here.

EECOLOR commented 1 month ago

The issue has been resolved! Thank you for the effort!