SAML

SAML

Only available in Sonatype Nexus RepositoryTM Pro. Interested in a free trial? Start here.

You can configure your instance to work with a SAML Identity Provider for authentication via Single Sign-On (SSO) and to send user groups to it for authorization. Nexus Repository implements the Web Browser SSO Profile from the SAML 2.0 specification. Supported bindings for sign-on are HTTP-POST (the default) and HTTP-Redirect for requests to the Identity Provider and HTTP-POST binding for responses from the Identity Provider. The Basic Attribute Profile is used for retrieving further information regarding the subjects and supported attributes are explained in SAML Configuration Details.

SAML provides access to the UI. For clients that don't support SSO, Nexus Repository can generate user tokens, which can be used instead of a user name and password for basic authentication or to make REST API calls.

SAML login requires SAML2_AUTH_REQUEST cookie beginning in release 3.89.0

Starting in Sonatype Nexus Repository 3.89.0-09, SAML authentication requires the SAML2_AUTH_REQUEST cookie to complete the login flow.

Tested SAML Providers and Minimal XML for Untested SAML Providers

We have tested the following providers with SAML and Nexus Repository: Auth0, Azure AD, Keycloak, Okta, OneLogin, PingFederate.

Below is a minimal XML example to help users with un-tested providers get SAML working. The following XML replaced some values with placeholders but demonstrates a simplified SAML XML:

<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" ID="id" entityID="https://sts.windows.net/hash/">
  <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <KeyDescriptor use="signing">
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <X509Data>
          <X509Certificate>
            certificate goes here
          </X509Certificate>
        </X509Data>
      </KeyInfo>
    </KeyDescriptor>
    <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://login.microsoftonline.com/hash/saml2"/>
    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://login.microsoftonline.com/hash/saml2"/>
    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://login.microsoftonline.com/hash/saml2"/>
  </IDPSSODescriptor>
</EntityDescriptor>

If you receive an "Invalid SAML metadata” error, try reducing the XML metadata to just the tags shown in the minimal example above.

Integrating with an Identity Provider

Configuring SAML requires the nx-all privilege and the following steps:

  1. Download the Identity Provider's SAML metadata file. This file may appear similar to the example below, which uses Keycloak as the Identity Provider:
<md:EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="http://localhost:8080/auth/realms/demo">
<md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:KeyName>Example_KeyName_Nexus</ds:KeyName>
<ds:X509Data>
<ds:X509Certificate>Example_Certificate_Data</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:ArtifactResolutionService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8080/auth/realms/demo/protocol/saml/resolve" index="0"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/auth/realms/demo/protocol/saml"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/auth/realms/demo/protocol/saml"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://localhost:8080/auth/realms/demo/protocol/saml"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/auth/realms/demo/protocol/saml"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:8080/auth/realms/demo/protocol/saml"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8080/auth/realms/demo/protocol/saml"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://localhost:8080/auth/realms/demo/protocol/saml"/>
</md:IDPSSODescriptor>
</md:EntityDescriptor>
  1. In Nexus Repository, upload the Identity Provider metadata.

  2. Download Nexus Repository's SAML metadata (also known as the service provider metadata) to provide to the Identity Provider. Note that some Identity Providers may be configured differently. It can be downloaded with the SAML REST API:

curl -u admin:admin123 -X GET "http://localhost:8081/service/rest/v1/security/saml/metadata"
  1. If applicable, upload Nexus Repository's SAML metadata (downloaded in the previous step) to the Identity Provider.

    • This is also referred to as registering a service provider to an Identity Provider.
    • If the Identity Provider does not allow uploading Nexus Repository's SAML metadata, then you can inspect it to extract the needed values. Also note that the "Audience" of your Identity Provider should be Nexus Repository's Entity ID, and its "Recipient" should be Nexus Repository's assertion consumer service URL. Please note that Nexus Repository's assertion consumer service URL is /saml.
  2. Configure the Identity Provider to send expected subject information as basic attributes. Note that these attribute names can be customized later.

  3. Enable the SAML Realm in Nexus Repository.

  4. Enable User Tokens in Nexus Repository.

Integration is complete and Single Sign-On using SAML is functional.

Uploading the Identity Provider Metadata and Configuring the Attribute Names Using the UI

Enabling the SAML Authentication Realm

Activate your SAML Realm by following these steps:

Best practice is to leave the Local Authenticating Realm activated so that the repository manager can be used by anonymous, admin and other users configured in this realm even with SAML authentication offline or unavailable. When users choose Sign In Without SSO, the other realms will be used for authentication, in the order they appear.

Enabling User Tokens

Activate User Tokens by the following steps:

The User Token Realm will automatically be added to the active Realms.
Refer to the section on User Tokens for more details.

SAML Configuration Details

Entity ID

Entity ID is a unique identifier that will be used when registering Nexus Repository to the Identity Provider as a service provider. It must be a valid URI. The default value <BaseUrl>/service/rest/v1/security/saml/metadata is recommended and normally there is no need to modify the Entity ID, but it is required if the deployed instance does not have a fixed URL or port.

Attribute Names

Nexus Repository expects the following basic SAML attributes to carry/extract the user information:

These attribute names must be configured on the Identity Provider, and must match the SAML Configuration in Nexus Repository. Note that the values are case-sensitive.
For example, if the Identity Provider sends the email information of a user with the attribute user-email-address, please make sure you configure the email attribute name to user-email-address in Nexus Repository as well.

All of these properties are optional to configure. If they are not explicitly configured, default values for them will be used.

Securing SAML Integration

Note

From Nexus Repository 3.27, if the SAML assertions are being signed, then the Identity Provider must set a destination field in the response that is set to the Nexus Assertion Consumer URL (<BaseURL>/saml).

Signed requests and responses between the Identity Provider and Nexus Repository are supported and recommended for security purposes. Signing responses can only be configured from the Identity Provider and not within Nexus Repository. In case signed messages are used and the Identity Provider's signature keys are renewed (or changed for any other reason), Identity Provider metadata in Nexus Repository's SAML configuration must be updated.

Nexus Repository's SAML configuration can be set to validate the Identity Provider's signature(s) on its response and/or its assertions within that response by setting

options. By default, if a signing key is found in the Identity Provider metadata, then Nexus Repository will attempt to validate signatures on the response and its assertions.

SAML Response Validation

Starting in Nexus Repository 3.88.0, the SAML library enforces stricter validation of entityId values in the SAML response. The following table identifies the XML elements validated against your Nexus Repository configuration:

SAML Response Element Validated Against Description
<saml:Audience> Entity ID configured in Nexus Repository The Service Provider (SP) entityId the Identity Provider includes in <saml:AudienceRestriction>. Must exactly match the Entity ID configured in Nexus Repository.
<saml:Issuer> entityID in the uploaded Identity Provider metadata The Identity Provider's identifier. Must match the entityID attribute in the IdP's SAML metadata uploaded to Nexus Repository.

Note

Starting in Nexus Repository 3.88.0, both values require exact string matching. A trailing slash difference, which is a common misconfiguration when using Microsoft Entra ID (formerly Azure AD), will cause authentication to fail.

SAML Response Example

A SAML Response from the Identity Provider will have the following form:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
  xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
  Destination="http://localhost:8081/saml"
  ID="ID_8c7224bc-a04d-43d8-8fb7-02747425b6d2"
  InResponseTo="ID_a6998aaa-5136-43e8-9f4f-dfff023509c8"
  IssueInstant="2019-09-09T15:27:33.971Z" Version="2.0">
  <saml:Issuer>http://localhost:8080/auth/realms/demo</saml:Issuer>
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
  </samlp:Status>
  <saml:Assertion ID="ID_526c9596-fedb-4909-ab27-7b15d5692c53"
    IssueInstant="2019-09-09T15:27:33.971Z" Version="2.0">
    <saml:Issuer>http://localhost:8080/auth/realms/demo</saml:Issuer>
    <saml:Subject>
      <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">
        nameId
      </saml:NameID>
      <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
        <saml:SubjectConfirmationData
          InResponseTo="ID_a6998aaa-5136-43e8-9f4f-dfff023509c8"
          NotOnOrAfter="2019-09-09T15:28:31.971Z"
          Recipient="http://localhost:8081/saml"/>
      </saml:SubjectConfirmation>
    </saml:Subject>
    <saml:Conditions NotBefore="2019-09-09T15:27:31.971Z"
      NotOnOrAfter="2019-09-09T15:28:31.971Z">
      <saml:AudienceRestriction>
        <saml:Audience>
          http://localhost:8081/service/rest/v1/security/saml/metadata
        </saml:Audience>
      </saml:AudienceRestriction>
    </saml:Conditions>
    <saml:AttributeStatement>
      <saml:Attribute FriendlyName="username" Name="username"
        NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:type="xs:string">jonny</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute FriendlyName="firstName" Name="firstName"
        NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:type="xs:string">John</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute FriendlyName="lastName" Name="lastName"
        NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:type="xs:string">Smith</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute FriendlyName="email" Name="email"
        NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:type="xs:string">jonny@example.com</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute FriendlyName="groups" Name="groups"
        NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:type="xs:string">group1</saml:AttributeValue>
        <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:type="xs:string">group2</saml:AttributeValue>
      </saml:Attribute>
    </saml:AttributeStatement>
  </saml:Assertion>
</samlp:Response>

User SAML Workflow

Once Nexus Repository is configured to use SAML, users can log into the Nexus Repository UI.

Below are some additional considerations:

After a user has logged into Nexus Repository, they can obtain a user token:

Revoking User Access

User access is revoked by doing the following:

To revoke user tokens for all users, you can use either one of the following actions:

curl -u admin:admin123 -X DELETE "http://localhost:8081/service/rest/v1/security/user-tokens"

To revoke the user token of a specific user, invoke the user token REST API using the following:

curl -u admin:admin123 -X DELETE "http://localhost:8081/service/rest/v1/security/users/{userId}/SamlRealm/user-token-reset"

Note that SAML does not allow notification of downstream systems when a user in the identity provider is deactivated. However, as soon as a user is deactivated in the identity provider, they will not be able to log into Nexus Repository using SAML.

If these users have user tokens, those will remain present in Nexus Repository.