Second Factor Only authentication allows a SP to authenticate only the second factor of a user. With SFO you can add two factor authentication to your institutions application gateway (e.g. Citrix Netscaler or F5 BIG-IP) or to the authentication or authorization gateway (e.g. Microsoft ADFS or Novell/NetIQ). SFO has its own authentication endpoint at SURFsecureID.
Once a user is registered with a second factor both SFO authentication and SURFsecureID can be used.
Feature | Standard authentication | SFO authenticaton |
---|---|---|
Authentication of first factor | Always | Never |
Authentication of second factor | Based on policy between IdP and SP | Always |
User registration | Using SURFsecureID selfservice registration and vetting by an RA | |
Standard SURFconext features | Attributes, Authorization, persistent identifiers | None |
With SFO the authentication via SURFconext is bypassed (see image below). This means that SURFconext functionality (e.g. attributes from the user's home IdP, the definition of authorization rules and persistent user identifiers) is not available.
Note that also with SFO the registration of users will be done by the institutions (IdP's): there is no work to be done for the SP.
To start a SFO the SP must send a SAML 2.0 AuthnRequest
to the SFO endpoint of the SURFsecureID Gateway. This request must:
urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
bindinghttp://www.w3.org/2001/04/xmldsig-more#rsa-sha256
algorithm (XML signatures cannot be used).RequestedAuthnContext
with an AuthnContextClassRef
with one of the defined levels.Subject
element as a NameID
(with Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
see description of AuthnRequest
in https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf, line 2001).SFO uses different SingleSignOn Location and AuthnConext
identifiers as compared with standard authentication.
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_zQIibz9FKixdlgX8E7bHqE29wfatcgbsPdVn0NN" Version="2.0" IssueInstant="2016-03-10T15:09:21Z" Destination="https://gw.stepup.example.org/gssp/2nd-factor-only/single-sign-on" AssertionConsumerServiceURL="https://application-gateway.some-organisation.example.org/consume-assertion" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"> <saml:Issuer>https://application-gateway.some-organisation.example.org/metadata</saml:Issuer> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">urn:collab:person:some-organisation.example.org:m1234567890</saml:NameID> </saml:Subject> <samlp:RequestedAuthnContext> <saml:AuthnContextClassRef>http://stepup.example.org/verified-second-factor/level2</saml:AuthnContextClassRef> </samlp:RequestedAuthnContext> </samlp:AuthnRequest> |
The signature is not visible in the XML: it will be encoded in HTTP GET parameters according to the specification of the HTTP-Redirect
binding.
The SURFconext identifier is built from identifiers that the IdP of the user sends to SURFconext during authentication:
urn:collab:person:{{urn:mace:terena.org:attribute-def:schacHomeOrganization}}:{{urn:mace:dir:attribute-def:uid}}
where:
urn:collab:person:
{{urn:mace:terena.org:attribute-def:schacHomeOrganization}}
= value of schacHomeOrganisation attribute of the user; same for all users and will be something like "institution.nl
".{{urn:mace:dir:attribute-def:uid}}
= value of uid
attribute of the user. Replace any "@" with an "_".For the value of last two items: ask the administrator of the IdP .
Example: urn:collab:person:some-organisation.example.org:m1234567890
The result of a successful authentication is a SAML Response
. It does not contain an AttributeStatement
.
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_ECAokbn0lm7lfVT7THQUl+dSbMrpeyAgiTv0+q16" Version="2.0" IssueInstant="2016-03-10T15:09:25Z" Destination="https://application-gateway.some-organisation.example.org/consume-assertion" InResponseTo="_zQIibz9FKixdlgX8E7bHqE29wfatcgbsPdVn0NN" > <saml:Issuer>https://gw.stepup.example.org/second-factory-only/metadata</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> </samlp:Status> <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_zQIibz9FKixdlgX8E7bHqE29wfatcgbsPdVn0NN" Version="2.0" IssueInstant="2016-03-10T15:09:25Z" > <saml:Issuer>https://gw.stepup.example.org/second-factory-only/metadata</saml:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /> <ds:Reference URI="#_1ROuxGVzJi5bbre6W4woNza82aK41HKjp6aKtw9r"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> <ds:DigestValue>YR5JFfJc1JZIKm7Ao3kXtDupEfeMrhKpD9T1lF1z0Lg=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>...</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>...</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">urn:collab:person:some-organisation.example.org:m1234567890</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2016-03-10T15:14:25Z" Recipient="https://application-gateway.some-organisation.example.org/consume-assertion" InResponseTo="_zQIibz9FKixdlgX8E7bHqE29wfatcgbsPdVn0NN" /> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2016-03-10T15:09:25Z" NotOnOrAfter="2016-03-10T15:14:25Z" > <saml:AudienceRestriction> <saml:Audience>https://application-gateway.some-organisation.example.org/metadata</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2016-03-10T15:09:25Z"> <saml:AuthnContext> <saml:AuthnContextClassRef>http://stepup.example.org/verified-second-factor/level2</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> </samlp:Response> |
When a user cannot be authenticated, the SURFsecureID gateway sends a SAML Response to the SP with a non success status:
urn:oasis:names:tc:SAML:2.0:status:Responder
with subcode urn:oasis:names:tc:SAML:2.0:status:AuthnFailed =
urn:oasis:names:tc:SAML:2.0:status:Responder
with subcode urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext =
See explanation at "Levels of Assurance".
SFO must be implemented at the SP. The authentication protocol is similar to the one used by the SURFsecureID gateway. The main difference is that the SP must send the identifier of the user in the Subject element of the SAML AuthnRequest (see description of AuthnRequest, line 2017).
You can find the metadata of the SFO endpoints on SURFsecureID Metadata for Service Providers.
Starting an SFO authentication will immediately start an authentication at the SURFsecureID gateway: a push notification (tqr) or an SMS will be sent to the user being authenticated. If authentication is started for the wrong user, this will derange the targeted user and in case of SMS, incur a cost to the institution and possibly for the user.
By observing the behavior of the SFO authentication it is possible to determine whether a username exists.
For this reasons we advise to perform a first factor authentication before starting a SFO authentication.
An example code for using SFO with SimpleSAMLphp can be found at: https://github.com/SURFnet/Stepup-SFO-demo