Page 1

Shibboleth Documentation Introduction Shibboleth is a super-set of SAML 2.0 that includes specifications for discovery, federation, artifact resolution etc. "Shibboleth" means two things: 1. The protocol for federated single-sign-on 2. The codebase or "product" produced by the project that can be run as an Identity Provider (IdP) (and its associated libraries) Instructure Canvas can consume SAML 2.0 identity assertions. As of today, we do not support the full Shibboleth protocol specifications, but can consume SAML 2.0 assertions originating from an appropriately configured Shibboleth (the product) identity provider.

Vocabulary Terms used: IdP: SP or Canvas SP: SSO:

Identity provider. In this case your Shibboleth server. Service provider. In this scenario, Instructure Canvas is the SP, consuming attributes asserted by your IdP. Single-Sign-On

Account Provisioning Instructure Canvas does not automatically create user accounts from successful single-sign-ons. User accounts must either be created manually in the web interface or through the SIS APIs. When Instructure Canvas receives a successful identity assertion from any of its supported authentication integrations, it searches for a user 'login' (or pseudonym if you're looking in the codebase) that matches the value of the asserted identity. If it finds a matching login, it logs in the associated user account. For example, if Instructure Canvas receives a SAML 2.0 assertion for a user and the value for the configured identity attribute is 'fred', Canvas will search for a login with a username of 'fred'. If one is


found, the associated user is logged in, otherwise the login is unsuccessful. Administrators can view/modify/create logins for users by clicking on the user account name in the search results for users. The search for user will search for email, SIS identifier, login username etc.

Configuration Settings

Log On URL URL where Canvas will redirect unauthenticated users. Address of your SAML 2.0 endpoint. Example: https://shib.myschool.edu/idp/profile/SAML2/Redirect/SSO Log Out URL URL where Canvas will redirect users when they log out. Change Password Link Since Canvas does not manage passwords in a SSO integration, we will direct users to this address to manage/maintain their password. Certificate Fingerprint The certificate is the public X.509 certificate that is used by the IdP to sign identity assertions. This is a representation in hex of the SHA1 hash of the public certificate. Since this is of the public certificate, it is not a secret value. Example: E9:A4:57:F0:BB:84:24:75:DB:56:D6:65:14:FC:9B:39:60:55:38:86 Identifier Format The identifier format informs both the IdP and SP of how to interpret the value desired for the NameID assertion (essentially the 'username'). Canvas includes this in the initial request to the IdP. Canvas does not interpret this value according to the associated semantic meaning of the attribute. Regardless of which format/attribute is chosen, Instructure Canvas will try to find a matching user-login. Example: urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified Login Release Valve To use a local Canvas password account in case your still perfecting the settings and locked yourself out, just add ?canvas_login=1 to your login URL. For instance: http://college-name.instructure.com/login?canvas_login=1


Step-by-Step Instructions Reminder: These instructions may need to be translated to your specific installation and configuration.

Calculate Certificate Fingerprint On the IdP OpenSSL will calculate the X.509 certificate fingerprint needed. If your certificate file is named idp.crt run: openssl x509 -noout -in idp.crt -fingerprint In Shibboleth 2, this may be located in /opt/shibboleth-idp/credentials/idp.crt If Ruby is more handy for you, you can calculate it out of the SAML XML assertion since it contains the certificate. require "openssl" require "digest/sha1" require 'base64' # snag the base64 encoded certificate from an assertion # it'll be in the tags <ds:X509Certificate>...</ds:X509Certificate> cert64 = "MIIDPjCCAiagAwIBAgIJANtc2N bmMudXMwHhcNMTEwNDA3MTQxMD ... LdBjEL0HPh0mr1ynZK4DSpncep" certificate_text = Base64.decode64(cert64) certificate = OpenSSL::X509::Certificate.new(certificate_text) fingerprint = Digest::SHA1.hexdigest(certificate.to_der) # print it out puts fingerprint

The example assertions below were generated urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified.

using

an

"Identifier

Format"

of

Create/verify Associated User Login Verify that you have a user under the Users tab with an associated login for the Shibboleth user account you're testing. In the subsequent examples, we assume a user named "Shib Test" with a login of "shibtest". "shibtest" must match the NameID sent across from the IdP. SP Meta Documents After you configure the SAML settings under the Institutional account's authentication settings, the page will provide you with a link to the meta documents describing the SP endpoint. You will need to save the XMLdocument referred to in the "Click here to see the service provider identity XML for this account" link. Example service meta data document <EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://www.instructure.com/saml2"> <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://mytest.instructure.com/saml_logout"/> <AssertionConsumerService index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://mytest.instructure.com/saml_consume"/> </SPSSODescriptor> <ContactPerson contactType="technical"> <SurName>Administrator</SurName> <EmailAddress>mailto:info@instructure.com</EmailAddress> </ContactPerson> </EntityDescriptor>

Save the XML snippet from the SP to a local file on the IdP, e.g. to:: /opt/shibboleth-idp/metadata/mytest.instructure.com.metadata.xml


Adjust IdP Configuration Files Remember to change as needed for your own particular situation. relying-party.xml Edit your /etc/shibboleth-idp/relying-party.xml file to let your IdP know about the Canvas SP. The Shibboleth IdP uses the meta data document from Canvas that you saved above. <!-- Instructure CANVAS metadata. Retrieved 6/9/11 from https://mytest.instructure.com/saml_meta_data --> <MetadataProvider id="CANVASMD" xsi:type="ResourceBackedMetadataProvider" xmlns="urn:mace:shibboleth:2.0:metadata" > <MetadataResource xsi:type="resource:FilesystemResource" file="/opt/shibboleth-idp/metadata/mytest.instructure.com.metadata.xml" /> </MetadataProvider>

Instructure Canvas uses HTTPS for all SAML 2.0 data transmissions. You may need to change the various references to encryptAssertion and encryptNameIDs from "conditional" to "never". They look like:: encryptAssertions="conditional"

encryptNameIds="conditional" />

attribute-resolver.xml Edit your /etc/shibboleth-idp/attribute-resolver.xml file to resolve a NameID attribute, encoded to the Identifier Format that you specified at the SP (Canvas). In this example, we generate an attribute named "principal" where the value is a duplicate of the "sAMAccountName" attribute which is determined by the Attribute Resolver with the id "myLDAP". The format is declared to match that specific in the Canvas configuration settings and is an attribute of type NameID. <!-- NameID for Instructure Canvas SP --> <resolver:AttributeDefinition id="principal" xsi:type="Simple" xmlns="urn:mace:shibboleth:2.0:resolver:ad" sourceAttributeID="sAMAccountName"> <resolver:Dependency ref="myLDAP" /> <resolver:AttributeEncoder xsi:type="enc:SAML2StringNameID" nameFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" /> </resolver:AttributeDefinition>

attribute-filter.xml Edit your /etc/shibboleth-idp/attribute-filter.xml file to add a policy for the Canvas SP. In this example, we create a rule that applies to the requester with the entity ID of "http://www.instructure.com/saml2" (the identity of the Instructure Canvas SP). This policy releases the NameID attribute named "principal" (configured above in attribute-resolver.xml) to Instructure Canvas, but only for users whose myMemberOf does NOT contain GshibDenyAccess. (This extra rule may not be needed for your IdP.) <!-- Instructure Canvas-specific rule --> <AttributeFilterPolicy id="InstructureCanvasPolicy"> <PolicyRequirementRule xsi:type="basic:AND"> <basic:Rule xsi:type="basic:NOT"> <basic:Rule xsi:type="basic:AttributeValueRegex" attributeID="myMemberOf" regex="^.*CN=GshibDenyAccess.*$"/> </basic:Rule> <basic:Rule xsi:type="basic:AttributeRequesterString" value="http://www.instructure.com/saml2"/> </PolicyRequirementRule> <AttributeRule attributeID="principal"> <PermitValueRule xsi:type="basic:ANY" /> </AttributeRule> </AttributeFilterPolicy>


idp-metadata.xml Edit /opt/shibboleth-idp/metadata/idp-metadata.xml and make sure you're using ONLY the <NameIDFormat> entry that matches the Identifier Format specified at the Canvas SP. This likely affects both the <IDPSSODescriptor> and <AttributeAuthorityDescriptor> elements. To keep with our example Canvas configuration settings, we use: <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>

(Note â&#x20AC;&#x201C; Steve says, "I'm not certain if its necessary to ONLY use that one, but I am pretty sure I MUST use at least that one entry â&#x20AC;Ś as the IdP bases its behavior partially on the settings in this file.") logging.xml Adjust your log settings for debugging purposes, in the file /etc/shibboleth-idp/logging.xml . Remember to change this back after you've gotten everything working if you don't want all these items to be logged all the time. <logger name="PROTOCOL_MESSAGE"> <level value="ALL" /> </logger> <logger name="edu.internet2.middleware.shibboleth.common.attribute"> <level value="ALL" /> </logger> You can view the logged events by tailing the log file: tail -f /var/log/shibboleth-idp/idp-process.log You will have to restart your Shibboleth IdP for these configuration settings to take effect.

SAML Messages End-to-End Now test it. Try logging on by pointing your browser at (for example): mytest.instructure.com We'll follow all the SAML exchanges for a successful login.

SAML message from SP to IdP This messages kicks off the SSO. Canvas sends this authentication request using an HTTP Redirect. Canvas advertises it's identity, http://www.instructure.com/saml2, and the URL of the Service (/saml_consume) where it will accept assertions using the HTTP POST bindings. It also requests the NameID attribute in the format specified in the configuration settings. <?xml version="1.0" encoding="UTF-8"?> <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://mytest.instructure.com/saml_consume" ID="3473bb1eb5a7ee527e31ffe1e286ad4121b356f7e5" IssueInstant="2011-06-17T20:45:47Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"> <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://www.instructure.com/saml2</saml:Issuer> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"/> <samlp:RequestedAuthnContext Comparison="exact" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <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>

SAML message from IDP to SP After the user successfully authenticates to the Shibboleth IdP, they are redirected back to Canvas using an HTTP POST where the payload is the following assertion. The assertion includes the signature, which is verified to have originated from the associated X.509 certificate.


Canvas computes the fingerprint of the supplied X.509 certificate and compares that with the fingerprint from the configuration settings. <?xml version="1.0" encoding="UTF-8"?> <saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://mytest.instructure.com/saml_consume" ID="_db75f64afd82d2f65c53982b93e94fa5" InResponseTo="3473bb1eb5a7ee527e31ffe1e286ad4121b356f7e5" IssueInstant="2011-06-17T20:46:03.621Z" Version="2.0"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">urn:mace:incommon:myschool.edu</saml2: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/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI="#_db75f64afd82d2f65c53982b93e94fa5"> <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/2000/09/xmldsig#sha1"/> <ds:DigestValue>GuPWrQwOVUMYVk2ETm4pYr+im0Q=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>A36yXZpeZBSAk5NA2j/wLeYhuX4vY1cdec...sEJqf6t6cGnf9TkSCdW5Csgb8uC9pPSg==</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIIDPjCCAiagAwIBAgIJANtc2NbmMudXMwHhcNMTEwNDA3MTQxMD...LdBjEL0HPh0mr1ynZK4DSpncep</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <saml2p:Status> <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </saml2p:Status> <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_aebdca06c494a406fda185373279d9dd" IssueInstant="2011-06-17T20:46:03.621Z" Version="2.0"> <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">urn:mace:incommon:myschool.edu</saml2:Issuer> <saml2:Subject> <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" //--- here above you see the configured format coming back NameQualifier="urn:mace:incommon:myschool.edu" SPNameQualifier="http://www.instructure.com/saml2"> shibtest //------ this is the value that Canvas will use to look up a user-login </saml2:NameID> <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml2:SubjectConfirmationData Address="192.168.1.1" InResponseTo="3473bb1eb5a7ee527e31ffe1e286ad4121b356f7e5" NotOnOrAfter="2011-06-17T20:51:03.621Z" Recipient="https://mytest.instructure.com/saml_consume"/> </saml2:SubjectConfirmation> </saml2:Subject> <saml2:Conditions NotBefore="2011-06-17T20:46:03.621Z" NotOnOrAfter="2011-06-17T20:51:03.621Z"> <saml2:AudienceRestriction> <saml2:Audience>http://www.instructure.com/saml2</saml2:Audience> </saml2:AudienceRestriction> </saml2:Conditions> <saml2:AuthnStatement AuthnInstant="2011-06-17T20:46:03.373Z" SessionIndex="903204ff20d9dfa711c654cd2af60d85fd2a13e3706846798ee38c8f302b4fdd"> <saml2:SubjectLocality Address="192.168.1.1"/> <saml2:AuthnContext> <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef> </saml2:AuthnContext> </saml2:AuthnStatement> </saml2:Assertion> </saml2p:Response>

After the user successfully authenticates to the Shibboleth IdP, they are redirected back to Canvas using an HTTP POST where the payload is the following assertion. The assertion includes the signature, which is verified to have originated from the associated X.509 certificate. Canvas computes the fingerprint of the supplied X.509 certificate and compares that with the fingerprint from the configuration settings. <?xml version="1.0" encoding="UTF-8"?> <saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://mytest.instructure.com/saml_consume" ID="_db75f64afd82d2f65c53982b93e94fa5" InResponseTo="3473bb1eb5a7ee527e31ffe1e286ad4121b356f7e5" IssueInstant="2011-06-17T20:46:03.621Z" Version="2.0"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">urn:mace:incommon:myschool.edu</saml2: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/2000/09/xmldsig#rsa-sha1"/> <ds:Reference URI="#_db75f64afd82d2f65c53982b93e94fa5"> <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/2000/09/xmldsig#sha1"/>

<ds:DigestValue>GuPWrQwOVUMYVk2ETm4pYr+im0Q=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>A36yXZpeZBSAk5NA2j/wLeYhuX4vY1cdec sEJqf6t6cGnf9TkSCdW5Csgb8uC9pPSg==</ds:SignatureValue>


<ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> MIIDPjCCAiagAwIBAgIJANtc2N bmMudXMwHhcNMTEwNDA3MTQxMD LdBjEL0HPh0mr1ynZK4DSpncep</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <saml2p:Status> <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </saml2p:Status> <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_aebdca06c494a406fda185373279d9dd" IssueInstant="2011-06-17T20:46:03.621Z" Version="2.0"> <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">urn:mace:incommon:myschool.edu</saml2:Issuer> <saml2:Subject> <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" //--- here above you see the configured format coming back NameQualifier="urn:mace:incommon:myschool.edu" SPNameQualifier="http://www.instructure.com/saml2"> shibtest //------ this is the value that Canvas will use to look up a user-login </saml2:NameID> <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml2:SubjectConfirmationData Address="192.168.1.1" InResponseTo="3473bb1eb5a7ee527e31ffe1e286ad4121b356f7e5" NotOnOrAfter="2011-06-17T20:51:03.621Z" Recipient="https://mytest.instructure.com/saml_consume"/> </saml2:SubjectConfirmation> </saml2:Subject> <saml2:Conditions NotBefore="2011-06-17T20:46:03.621Z" NotOnOrAfter="2011-06-17T20:51:03.621Z"> <saml2:AudienceRestriction> <saml2:Audience>http://www.instructure.com/saml2</saml2:Audience> </saml2:AudienceRestriction> </saml2:Conditions> <saml2:AuthnStatement AuthnInstant="2011-06-17T20:46:03.373Z" SessionIndex="903204ff20d9dfa711c654cd2af60d85fd2a13e3706846798ee38c8f302b4fdd"> <saml2:SubjectLocality Address="192.168.1.1"/> <saml2:AuthnContext> <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef> </saml2:AuthnContext> </saml2:AuthnStatement> </saml2:Assertion> </saml2p:Response>

The requested NameID format was successfully sent back to the Canvas SP, as the following sub-snippet from above. Note it has "shibtest" as its value: <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="urn:mace:incommon:myschool.edu" SPNameQualifier="http://www.instructure.com/saml2">shibtest</saml2:NameID>

Acknowledgements Much of the credit for this documentation goes to Steve Thorpe who provided all of the Shibboleth IdP instructions. He rocks.

Canvas Shibboleth Integration  

Canvas Shibboleth Integration