Alfresco Share SAML Version 1.1 Revisions 1.1 1.1.1 IDP & Alfresco user logs in using saml login page (Added info about saving the username and IDP login date as a solution for the Security concern mentioned in v1.0) 2. Assert user is an IDP user (solution for the Security concern mentioned in v1.0) 2. Change of urls (Now has a header) 2.2.4. User signed up to an Alfresco network with an IDP that (at the time) had auto provisioning enabled (but now is disabled ) (Changed) 2.2.5. User signed up to an Alfresco network that (at the time) did NOT use an IDP (but now has an IDP) (Added) 4. SIGNUP/INVITE PROFILE FORMS (REDIRECT) (Added) 1.0 First version Introduction The goal of this document is to describe what needs to be implemented in Share to support a subset of SAML in the Cloud. The SAML support discussed is Authentication Request Protocol which will be implemented using the HTTP POST Binding profile. http://en.wikipedia.org/wiki/saml_2.0#authentication_request_protocol http://en.wikipedia.org/wiki/saml_2.0#http_post_binding See appendix for suggestions to tasks and estimates (totally 4 tasks).
Review: Use cases & Application flow 1. LOGIN FLOWS 1.1. IDP & Alfresco user logs in using saml login page Implementation: See Appendix I.1.1 1. User visits his network s SAML login page, https://my.alfresco.com/share/{network}/saml. This is a blank/white page that directly and automatically will point the user to the network s IDP server (meaning that the user will at most see a white flash of this page). The page will point the user to the IDP by first asking the Alfresco repository for a SAML AuthnRequest which will be included in as the SAMLRequest parameter in a hidden form that will be POST :ed to the IDP s authn service. 2. At the IDP the user will be presented a login form (unless already logged in) Once identified the IDP will make the users browser perform HTTP POST against Share with a SAMLResponse parameter containing the AuthnResponse. 3. Share s SAMLAuthnResponseController will handle the POST and ask the repo to verify the AuthnResponse. 4. The repository verifies the AuthnResponse and will save the username and the date and time when the login was done at the IDP (This information will be used by workflows to assert that the user has a profile at the IDP, in other words this information shall be stored for NON existing Alfresco users as well). After a successful verification the username & a ticket is returned. 5. The SAMLAuthnResponseController logs in the user into Share and will use an alfresco ticket to identify himself when communicating with the repository. 1.2. IDP & Alfresco user logs in using default login page Implementation: See Appendix I.1.2 Hook points in Share (or Spring Surf) will be used to make sure that if a user (of an IDP controlled network) is trying to login using the default login page, https://my.alfresco.com/share/, the login request will be aborted and the user will be redirected to the network s SAML login page mentioned above, where the same flow will be used.
1.3. IDP user (without Alfresco profile) logs in Implementation: SAMLAuthnResponseController User logs in at IDP but when redirected back to Alfresco Cloud no profile will be found. Share will in this case display a page with some help text. If the network has auto provision enabled the help text will read something like: To be able to login you need to sign up for an Alfresco Cloud account, to do that, please click here. If the network has auto provision disabled the help text will read something like: Please contact your system administrator and ask him to invite you to Alfresco Cloud. 1.4. Alfresco user (without IDP profile) tries to login to a network that suddenly is under IDP control User tries to login to Alfresco, but login will be aborted when Alfresco realises the network is under IDP control. The user will be redirected to the IDP where he will not be able to login since he does NOT have a profile at the IDP. Not ideal, but not much we can do I assume. 2. INVITE FLOWS Assert user is an IDP user The following logic shall be added to the workflows when a profile is being submitted and a user is about to be created in a network that is under IDP control. 1. If the username has NOT been used to log in at the IDP (done by inspecting when the username has been used to login at the IDP, see 1.1:4). a. Return an error with a specific error code 2. If network is under IDP control. a. If auto provisioning is enabled i. Create user b. If auto provisioning is disabled and initiated by SiteManager i. Create user c. If auto provisioning is disabled and initiated by a NON SiteManager
i. NOT create user and return an error with a specific error code This is to make sure that user s can t bypass the IDP login during the signup/invite process by creating a default invite/signup link that goes directly to the complete profile page (by using the information in the idp invite/signup links sent out in the emails) and thus create an alfresco user without having a IDP profile (which then could be used to access Alfresco using the mobile & webdav interfaces). See next section for more information about the links. Change of urls All urls sent out in signup/invite email from networks under IDP control shall route the user to the network s SAML login page with an extra url page parameter to enable the user to be redirected to the signup/invite pages after logging in at the IDP. This means that there should still be reject and approve links in the workflow emails but that they for IDP controller networks shall be slightly different. A default invite/signup link used by networks NOT using and IDP: http://my.alfresco.com/share/ system /page/activation?key=<key>&id=<id> An idp invite/signup link user by networks that use an IDP (the value of the page parameter MUST be url encoded): http://my.alfresco.com/share/<network>/saml?page= activation%3fkey%3d<key>%26id%3d<id > Note! Share will store the value of the page parameter as a org.alfresco.share.saml.loginredirectpage cookie to remember where to redirect the user when coming back from the IDP. There is an SAML attribute called RelayState to support this, but since the invite/signup id & key are the only values you will need to get access to Alfresco we do not want to expose such sensitive information to external systems. 2.1. IDP user signed up to an Alfresco network with an IDP (auto provision enabled ) 1. User gets an email with a link to the network s SAML login page, with a page parameter containing the url to the complete profile form page (that will be stored as a cookie with current domain and /share as path). The network s SAML login page, will immediately redirect the user
to the IDP by making the browser POST a AuthnRequest in a hidden form. 2. User will get a login form at the IDP (unless already logged in) and will after being identified get redirected back to Share where Share s SamlAuthnResponseController will ask the repository to verify the response. The repository will say that the SAML AuthnResponse is OK but will also realise that the user does NOT exist in Alfresco, and will therefore NOT return a ticket. The repository will however save the information that the username was used in a successful login at the IDP. 3. Share will not login the user since there s no ticket returned, but instead redirect him to the Share page defined by the page parameter (saved as a cookie), in other words the user will be taken to the complete profile form page. Note! Since the user wasn t found in Alfresco the user will NOT be logged into Share. 3. The user completes the profile form s firstname, lastname & (Alfresco) password fields which is submitted using ajax, meaning the user will not leave the page. (The repository will in this case check that the username has been used to login at the IDP). 4. The user has now been created in Alfresco but is still NOT logged in to Share. To actually login the user the complete profile form page will POST a hidden form with... a. username b. password The local alfresco password the user just entered c. success the url to go after a successful login, in this case the user s dashboard...to the standard Share login url ( /share/page/dologin ). 4. However since the LoginController in Share has been overridden, it will first check if the username is under IDP control, which it is. Meaning that the user will once again go to the networks SAML login page, but this time with the page parameter set to the success 5. The network s SAML login page will once again redirect the user to the IDP by doing a POST of a hidden form with a (new) AuthnRequest. 6. When the user comes to the IDP this time the user is already logged in, meaning no login form will be displayed (unless the user took longer than 5 minutes to complete the profile form). The user will be redirected back to Alfresco with a new AuthnResponse. 7. This time the user will be found in Alfresco and the user will be logged into Share using the ticket returned by the Alfresco repository. 8. The user will be redirected to his dashboard.
2.2. IDP user signed up to an Alfresco network with an IDP (auto provision disabled ) User will get an email saying he needs to contact the network s administrator and request a sign up (since the network is under IDP control). 2.3. IDP user (without Alfresco profile) was invited to an Alfresco network with an IDP The flow will be almost exactly like the steps for the signup described in User signed up to a network with an IDP (auto provision enabled ). The only difference is that the user will end up on the networks dashboard instead of the user dashboard. (As expected) 2.4. User signed up to an Alfresco network with an IDP that (at the time) had auto provisioning enabled (but now is disabled ) 1. User got an invite email with a idp link to the network s SAML login page and a page url parameter that will redirect him to the complete profile page after logging in at the IDP. 2. User does NOT click the link in the email. 3. Networks administrator disables auto provisioning. 4. User clicks the link in the email, logs in at the IDP and gets redirected to the complete profile page. 5. When submitting the profile form the repository will see that auto provisioning is disabled and MUST return an error and shall NOT allow the creation (however invites created by a SiteManager shall be allowed to create users). 2.5. User signed up to an Alfresco network that (at the time) did NOT use an IDP (but now has an IDP) 1. User got an invite email with a direct link to the complete profile page. 2. User does NOT click the email. 3. Networks administrator enables SAML with an IDP.
4. User clicks the link in the email and goes to the complete profile page. 5. When submitting the profile form the repository will note that the username has NOT logged in at the IDP and therefor return an error. 6. Share redirects user to networks SAML login with the page parameter set to the current page the complete profile form for the invite/signup. 3. LOGOUT When logging in to the IDP (Ping Federrer) the user will be logged in for 5 minutes (if I remember Jamal correctly), in Share he will be logged in for 60 minutes. When clicking Logout in Alfresco Share the user will only be logged out from and Share. No communication with the IDP will take place and the user will therefore remain logged in.however since the timeout is 5 minutes there is a very strong chance the user actually is logged out anyway. This is the solution we are thinking of implementing in the first version the first cut. If we want to support single log out (SLO) we will need to plan it further. In the parts that I investigated I could not see that it would cause any problems. The work required would probably involve ~2 3 days of further investigation & design plus ~6 8 days of actual implementation & testing. 4. FORGOT PASSWORD Users in networks with an IDP use the password at the IDP to login to Share, to reset their IDP password they will have to follow instructions from their company/idp. If an IDP user, however wants to reset his mobile/webdav password it would be done, just like any other Alfresco Cloud user. No code in Share needs to be changed, unless additional help text shall be added in the UI, i.e. the Forgot password screen but I haven t seen any such requirements.
APPENDIX Implementation 1. NETWORK S SAML LOGIN PAGE (AUTHN REQUEST) Estimate: 2 days Shorten the url for the network s SAML login page... urlrewrite.xml <rule> <from>^/([^/]+)/saml</from> <to>/page/saml authnrequest</to> <set name="org.alfresco.cloud.tenant.name">$1</set> </rule> Define the page... saml authnrequest.xml Use Share s redirect template Include the saml authnrequest.get webscript Define the (new) redirect template in slingshot... redirect.xml & redirect.ftl New white template including no resources but the components to make page loading as quick as possible.
Define the component that will send the user to the network s IDP with a SAML authentication request... saml authnrequest.get.desc.xml 1. Call an un authenticated repo webscript to get a new SAML AuthnRequest and the url to the idp s AuthnRequest service. 2. Take the value of page url parameter and store it as a cookie. (So the SAMLAuthnResponseController knows where to direct the browser when the user comes back from the IDP). 3. Create a hidden form with a SamlRequest parameter with a value of the (Base64 encoded and signed) AuthnRequest xml snippet. 4. Automatically post the hidden form to the IDP. 2. SAML AUTHN RESPONSE CONTROLLER Estimate: 3 days Override the webframeworkhandlermappings bean and add... custom slingshot cloud context.xml /saml authnresponse**=samlauthnresponsecontroller Add new samlauthnresponsecontroller bean... custom slingshot cloud context.xml <bean id="samlauthnresponsecontroller" class="org.alfresco.web.site.servlet.samlauthnresponsecontroller"> <property name="cacheseconds" value=" 1" /> <property name="useexpiresheader"><value>true</value></property> <property name="usecachecontrolheader"><value>true</value></property> </bean> Create the samlauthnresponsecontroller that will handle the POST from the IDP...
SAMLAuthnResponseController.java 1. Accept only POST requests. 2. Call SAMLTenantUserFactory s authenticate method with the posted AuthnResponse as parameter. 3. If user was authenticated marks session as logged in using: AuthenticationUtil.login(request, response, username, false); 4. Redirect the user to the value of the org.alfresco.share.saml.loginredirectpage cookie. 5. Clear the value of the cookie. Note! If there is no ticket the user didn t exist in Alfresco and should be redirected to a help page saying something like Click here to signup to Alfresco Cloud (if auto provision is enabled) OR Please contact your sysadmin to access Alfresco Cloud (if auto provision is disabled). If however the page redirect cookie was set it shall always be followed since it may contain a link to a signup/invite for a non existing user. Create the saml user factory... SAMLTenantUserFactory.java 1. Add the authenticate method that accepts a SAMLResponse <String>. 2. Calls the repo with the SAMLResponse and get back a ticket & a username. (using the alfresco noauth connector) 3. Create a ticket based Connector for the " alfresco " endpoint 4. Make sure the user will get constructed. Create the login help page... saml login help.xml 1. Use the simple guest template 2. Include the saml login help.get.desc.xml webscript Create the login help component... saml login help.get.desc.xml
1. Check if the network is under idp control and have auto provisioning a. enabled Display message with link to sign up page b. disabled Display message asking user to contact networks administrator. 3. NORMAL LOGIN PAGE (REDIRECT) Estimate: 1 day Override LoginController... TenantLoginController.java 1. Call the repo with the username and check if user is under IDP control (using the alfresco noauth connector) a. If under IDP control: redirect user to network s SAML login page Note! Make sure the success parameter is set as the page parameter. b. If NOT under IDP control: just call superclass. 4. SIGNUP/INVITE PROFILE FORMS (REDIRECT) Estimate: 2 days React to new specific error codes when profile creation fails. account completion.js If profile couldn t be created check the error code 1. When the user has NOT logged into the IDP before completing the profile Redirect user to networks SAML login with the page parameter set to the current page the complete profile form for the invite/signup. 2. When the network has auto provisioning disabled and the invite was done form a NON Site Manager Display error message