// Setup advanced info about metadata @Bean public ExtendedMetadata extendedMetadata() { ExtendedMetadata extendedMetadata = new ExtendedMetadata(); extendedMetadata.setIdpDiscoveryEnabled(true); extendedMetadata.setSignMetadata(false); return extendedMetadata; }
/** * Initializes SSO by creating AuthnRequest assertion and sending it to the IDP using the default * binding. Default IDP is used to send the request. * * @param options values specified by caller to customize format of sent request * @throws SAMLException error initializing SSO * @throws SAMLRuntimeException in case context doesn't contain required entities or contains * invalid data * @throws MetadataProviderException error retrieving needed metadata * @throws MessageEncodingException error forming SAML message */ public void sendAuthenticationRequest(SAMLMessageContext context, WebSSOProfileOptions options) throws SAMLException, MetadataProviderException, MessageEncodingException { // Verify we deal with a local SP if (!SPSSODescriptor.DEFAULT_ELEMENT_NAME.equals(context.getLocalEntityRole())) { throw new SAMLException( "WebSSO can only be initialized for local SP, but localEntityRole is: " + context.getLocalEntityRole()); } // Load the entities from the context SPSSODescriptor spDescriptor = (SPSSODescriptor) context.getLocalEntityRoleMetadata(); IDPSSODescriptor idpssoDescriptor = (IDPSSODescriptor) context.getPeerEntityRoleMetadata(); ExtendedMetadata idpExtendedMetadata = context.getPeerExtendedMetadata(); if (spDescriptor == null || idpssoDescriptor == null || idpExtendedMetadata == null) { throw new SAMLException( "SPSSODescriptor, IDPSSODescriptor or IDPExtendedMetadata are not present in the SAMLContext"); } log.debug( "idpExtendedMetadata.getSigningAlgorithm=" + idpExtendedMetadata.getSigningAlgorithm()); idpExtendedMetadata.setSigningAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"); SingleSignOnService ssoService = getSingleSignOnService(options, idpssoDescriptor, spDescriptor); AssertionConsumerService consumerService = getAssertionConsumerService(options, idpssoDescriptor, spDescriptor); AuthnRequest authRequest = getAuthnRequest(context, options, consumerService, ssoService); if (authRequest == null) { throw new SAMLException("Erreur dans getAuthnRequest null"); } // authRequest.setForceAuthn(Boolean.TRUE); log.debug("getAuthnRequest.providerName=" + authRequest.getProviderName()); // TODO optionally implement support for conditions, subject context.setCommunicationProfileId(getProfileIdentifier()); context.setOutboundMessage(authRequest); context.setOutboundSAMLMessage(authRequest); context.setPeerEntityEndpoint(ssoService); context.setPeerEntityRoleMetadata(idpssoDescriptor); context.setPeerExtendedMetadata(idpExtendedMetadata); if (options.getRelayState() != null) { context.setRelayState(options.getRelayState()); } boolean sign = spDescriptor.isAuthnRequestsSigned() || idpssoDescriptor.getWantAuthnRequestsSigned(); log.debug("signature?" + sign + " avec http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"); context .getLocalExtendedMetadata() .setSigningAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"); sendMessage(context, sign); SAMLMessageStorage messageStorage = context.getMessageStorage(); if (messageStorage != null) { messageStorage.storeMessage(authRequest.getID(), authRequest); } }
/** * Method populates fields localEntityId, localEntityRole, localEntityMetadata, * localEntityRoleMetadata and peerEntityRole. In case fields localAlias, localEntityId, * localEntiyRole or peerEntityRole are set they are used, defaults of default SP and IDP as a * peer are used instead. * * @param samlContext context to populate * @throws org.opensaml.saml2.metadata.provider.MetadataProviderException in case metadata do not * contain expected entities or localAlias is specified but not found */ private void populateLocalEntity(SAMLMessageContext samlContext) throws MetadataProviderException { String localEntityId = samlContext.getLocalEntityId(); QName localEntityRole = samlContext.getLocalEntityRole(); if (localEntityId == null) { throw new MetadataProviderException( "No hosted service provider is configured and no alias was selected"); } EntityDescriptor entityDescriptor = metadata.getEntityDescriptor(localEntityId); RoleDescriptor roleDescriptor = metadata.getRole(localEntityId, localEntityRole, SAMLConstants.SAML20P_NS); ExtendedMetadata extendedMetadata = metadata.getExtendedMetadata(localEntityId); if (entityDescriptor == null || roleDescriptor == null) { throw new MetadataProviderException( "Metadata for entity " + localEntityId + " and role " + localEntityRole + " wasn't found"); } samlContext.setLocalEntityMetadata(entityDescriptor); samlContext.setLocalEntityRoleMetadata(roleDescriptor); samlContext.setLocalExtendedMetadata(extendedMetadata); if (extendedMetadata.getSigningKey() != null) { samlContext.setLocalSigningCredential( keyManager.getCredential(extendedMetadata.getSigningKey())); } else { samlContext.setLocalSigningCredential(keyManager.getDefaultCredential()); } }
/** * @param args * @throws IOException * @throws MarshallingException */ public static void main(final String[] args) throws Exception { final Arguments arguments = new Arguments(); final JCommander commander = new JCommander(arguments); try { commander.parse(args); } catch (final ParameterException e) { System.err.println(e.getMessage()); final StringBuilder builder = new StringBuilder(); commander.usage(builder); System.err.println(builder); return; } final KeyStore keystore = KeyStore.getInstance("jks"); InputStream keystoreStream = null; try { keystoreStream = new FileInputStream(arguments.getKeystore()); keystore.load(keystoreStream, arguments.getKeystorePassword().toCharArray()); } finally { if (keystoreStream != null) keystoreStream.close(); } final Map<String, String> keyPasswords = new HashMap<>(); if (arguments.getEncryptionKey() != null) keyPasswords.put(arguments.getEncryptionKey(), arguments.getEncryptionKeyPassword()); if (arguments.getSigningKey() != null) keyPasswords.put(arguments.getSigningKey(), arguments.getSigningKeyPassword()); if (arguments.getTlsKey() != null) keyPasswords.put(arguments.getTlsKey(), arguments.getTlsKeyPassword()); bootstrap(); final JKSKeyManager keyManager = new JKSKeyManager(keystore, keyPasswords, null); final MetadataGenerator generator = new MetadataGenerator(); generator.setKeyManager(keyManager); generator.setEntityId(arguments.getEntityId()); generator.setEntityAlias(arguments.getAlias()); generator.setEntityBaseURL(arguments.getBaseURL()); generator.setSignMetadata(arguments.isSignMetadata()); generator.setRequestSigned(arguments.isRequestSigned()); generator.setWantAssertionSigned(arguments.isWantAssertionSigned()); generator.setSigningKey(arguments.getSigningKey()); generator.setEncryptionKey(arguments.getEncryptionKey()); if (arguments.getTlsKey() != null && arguments.getTlsKey().length() > 0) { generator.setTlsKey(arguments.getTlsKey()); } final Collection<String> bindingsSSO = new LinkedList<String>(); final Collection<String> bindingsHoKSSO = new LinkedList<String>(); final AllowedSSOBindings defaultBinding = arguments.getSsoDefaultBinding(); int assertionConsumerIndex = 0; for (final AllowedSSOBindings binding : arguments.getSsoBindings()) { // Set default binding if (binding.equals(defaultBinding)) { assertionConsumerIndex = bindingsSSO.size() + bindingsHoKSSO.size(); } // Set included bindings if (AllowedSSOBindings.SSO_POST.equals(binding)) { bindingsSSO.add(SAMLConstants.SAML2_POST_BINDING_URI); } else if (AllowedSSOBindings.SSO_ARTIFACT.equals(binding)) { bindingsSSO.add(SAMLConstants.SAML2_ARTIFACT_BINDING_URI); } else if (AllowedSSOBindings.SSO_PAOS.equals(binding)) { bindingsSSO.add(SAMLConstants.SAML2_PAOS_BINDING_URI); } else if (AllowedSSOBindings.HOKSSO_POST.equals(binding)) { bindingsHoKSSO.add(SAMLConstants.SAML2_POST_BINDING_URI); } else if (AllowedSSOBindings.HOKSSO_ARTIFACT.equals(binding)) { bindingsHoKSSO.add(SAMLConstants.SAML2_ARTIFACT_BINDING_URI); } } // Set bindings generator.setBindingsSSO(bindingsSSO); generator.setBindingsHoKSSO(bindingsHoKSSO); generator.setAssertionConsumerIndex(assertionConsumerIndex); // Discovery if (arguments.isIncludeDiscovery()) { generator.setIncludeDiscovery(true); if (arguments.getCustomDiscoveryURL() != null && arguments.getCustomDiscoveryURL().length() > 0) { generator.setCustomDiscoveryURL(arguments.getCustomDiscoveryURL()); } } else { generator.setIncludeDiscovery(false); } generator.setNameID(arguments.getNameID()); final EntityDescriptor descriptor = generator.generateMetadata(); final ExtendedMetadata extendedMetadata = generator.generateExtendedMetadata(); extendedMetadata.setSecurityProfile(arguments.getSecurityProfile()); extendedMetadata.setSslSecurityProfile(arguments.getSslSecurityProfile()); extendedMetadata.setRequireLogoutRequestSigned(arguments.isRequireLogoutRequestSigned()); extendedMetadata.setRequireLogoutResponseSigned(arguments.isRequireLogoutResponseSigned()); extendedMetadata.setRequireArtifactResolveSigned(arguments.isRequireArtifactResolveSigned()); Writer metadataWriter = null; try { metadataWriter = new FileWriter(arguments.getMetadataOutput()); metadataWriter.write(getMetadataAsString(descriptor)); } finally { if (metadataWriter != null) { metadataWriter.flush(); metadataWriter.close(); } } if (arguments.getExtendedMetadataOutput() != null) { Writer extendedMetadataWriter = null; try { extendedMetadataWriter = new FileWriter(arguments.getExtendedMetadataOutput()); extendedMetadataWriter.write( getConfiguration(arguments.getExtendedMetadataOutput().getName(), extendedMetadata)); } finally { if (extendedMetadataWriter != null) { extendedMetadataWriter.flush(); extendedMetadataWriter.close(); } } } }
private static String getConfiguration( final String fileName, final ExtendedMetadata extendedMetadata) { final StringBuilder sb = new StringBuilder(); sb.append( "<bean class=\"org.springframework.security.saml.metadata.ExtendedMetadataDelegate\">\n"); sb.append(" <constructor-arg>\n"); sb.append( " <bean class=\"org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider\">\n"); sb.append(" <constructor-arg>\n"); sb.append(" <value type=\"java.io.File\">classpath:security/") .append(fileName) .append("</value>\n"); sb.append(" </constructor-arg>\n"); sb.append(" <property name=\"parserPool\" ref=\"parserPool\"/>\n"); sb.append(" </bean>\n"); sb.append(" </constructor-arg>\n"); sb.append(" <constructor-arg>\n"); sb.append( " <bean class=\"org.springframework.security.saml.metadata.ExtendedMetadata\">\n"); sb.append(" <property name=\"local\" value=\"true\"/>\n"); sb.append(" <property name=\"alias\" value=\"") .append(extendedMetadata.getAlias()) .append("\"/>\n"); sb.append(" <property name=\"securityProfile\" value=\"") .append(extendedMetadata.getSecurityProfile()) .append("\"/>\n"); sb.append(" <property name=\"sslSecurityProfile\" value=\"") .append(extendedMetadata.getSslSecurityProfile()) .append("\"/>\n"); sb.append(" <property name=\"signingKey\" value=\"") .append(extendedMetadata.getSigningKey()) .append("\"/>\n"); sb.append(" <property name=\"encryptionKey\" value=\"") .append(extendedMetadata.getEncryptionKey()) .append("\"/>\n"); if (extendedMetadata.getTlsKey() != null) { sb.append(" <property name=\"tlsKey\" value=\"") .append(extendedMetadata.getTlsKey()) .append("\"/>\n"); } sb.append(" <property name=\"requireArtifactResolveSigned\" value=\"") .append(extendedMetadata.isRequireArtifactResolveSigned()) .append("\"/>\n"); sb.append(" <property name=\"requireLogoutRequestSigned\" value=\"") .append(extendedMetadata.isRequireLogoutRequestSigned()) .append("\"/>\n"); sb.append(" <property name=\"requireLogoutResponseSigned\" value=\"") .append(extendedMetadata.isRequireLogoutResponseSigned()) .append("\"/>\n"); if (extendedMetadata.isIdpDiscoveryEnabled()) { sb.append(" <property name=\"idpDiscoveryURL\" value=\"") .append(extendedMetadata.getIdpDiscoveryURL()) .append("\"/>\n"); sb.append(" <property name=\"idpDiscoveryResponseURL\" value=\"") .append(extendedMetadata.getIdpDiscoveryResponseURL()) .append("\"/>\n"); } sb.append(" </bean>\n"); sb.append(" </constructor-arg>\n"); sb.append("</bean>"); return sb.toString(); }