Several authentication mechanisms can be used for VMware Cloud Director users. The basic authentication is used for local (users stored in VCD database) and LDAP users. SAML authentication can be used for integration with SAML compatible Identity Providers such as Microsoft AD FS, IBM Cloud Identity, VMware Workspace ONE Access (VIDM). OAuth authentication is supported as well, but due to the fact you have to (currently as of VCD 10.2) use API to configure it, it is not that widely known.
In this article I will show an example of such configuration with VMware Identity Manager (VIDM) and with Google Identity IdP. Yes, with VIDM you have the option to use SAML or OAuth.
By default OAuth authentication can be enabled by the tenant at Organizational level and co-exist with local, LDAP and SAML identity sources. The OAuth authentication endpoint must be reachable from VCD Cells. This is a big difference compared to SAML authentication, which is performed via assertion token exchange via browser (only the client browser needs to reach the SAML IdP). Therefore OAuth is more suitable when public IdPs are used (e.g. Google) or provider managed ones (VCD cells can reach IdP internally).
VMware Identity Manager OAuth Configuration
Note I am using VIDM version 3.3.
- In VIDM as admin go to Catalog, Settings, Remote App Access and create a new Client
- Create the client. Pick unique Client ID, the redirect URL is https://vcd.example.com/login/oauth?service=tenant:<org name> or https://vcd.example.com/login/oauth?service=provider. Generate the shared secret and select Email, Profile, User and OpenID scopes.
- Now we need to find OAuth endpoints and public key. In my VIDM configuration this is can be found at https://vidm.example.com/SAAS/auth/.well-known/openid-configuration. This URL can differ based on VIDM / Workspace ONE Access version.
The address returns a JSON response from which we need: issuer, authorization_endpoint, token_endpoint, userinfo_endpoint, scopes and claims supported.
The link to the public key is provided in jwks_uri (https://vidm.example.com/SAAS/API/1.0/REST/auth/token?attribute=publicKey&format=jwks). We will need the key in PEM format, so you can either convert it (e.g. https://8gwifi.org/jwkconvertfunctions.jsp) or specify PEM format in the link (&format=pem at the end of the URI). We will also need KeyID (kid value) and key algorithm (kty). - Now we have all necessary information to configure OAuth in VCD. We will use PUT /admin/org/{id}/settings/oauth API call. In the payload we will provide all data that we collected in steps #2 and #3. Here is an example I used:
Note the OIDCAttributeMapping section. Here we must specify claims providing more information about the user. VIDM currently does not support groups and roles, so those are hardcoded. You can see what user information is sent by accessing UserInfoEndpoint. This can be done easily with Postman OAuth2 authentication, where you first obtain the Access Token (orange button) and then do a GET against the UserInfoEndpoint.
- Lastly we need to import some users. This is done with POST /admin/org/{id}/users API call with ProviderType set to OAUTH.
Now we can log in as the VIDM user.
Google Identity OAuth Configuration
- Head over to Credentials section of Google API & Services: https://console.developers.google.com/apis/credentials
- Create Project, configure Consent Screen, Scopes and test users
- Create OAuth Client ID. Use the redirect URI https://vcd.example.com/login/oauth?service=tenant:<org name> or https://vcd.example.com/login/oauth?service=provider. Note generated Client ID and secret.
- Google OAuth endpoints and public keys can be retrieved from: https://accounts.google.com/.well-known/openid-configuration
You will need to get both public keys and convert them to PEM. Now we can configure the OAUTH in VCD.
PUT https://{{host}}/api/admin/org/b813a16e-6821-4dc5-994f-955b10155107/settings/oauth <OrgOAuthSettings xmlns="http://www.vmware.com/vcloud/v1.5" type="application/vnd.vmware.admin.organizationOAuthSettings+xml"> <IssuerId>https://accounts.google.com</IssuerId> <OAuthKeyConfigurations> <OAuthKeyConfiguration> <KeyId>eea1b1f42807a8cc136a03a3c16d29db8296daf0</KeyId> <Algorithm>RSA</Algorithm> <Key>-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0zNdxOgV5VIpoeAfj8TM EGRBFg+gaZWz94ePR1yxTKzScHakH4F4wcMEyL0vNE+yW/u4pOl9E+hAalPa2tFv 4fCVNMMkmKwcf0gm9wNFWXGakVQ8wER4iUg33MyUGOWj2RGX1zlZxCdFoZRtshLx 8xcpL3F5Hlh6m8MqIAowWtusTf5TtYMXFlPaWLQgRXvoOlLZ+muzEuutsZRu+agd OptnUiAZ74e8BgaKN8KNEZ2SqP6vE4w16mgGHQjEPUKz9exxcsnbLru6hZdTDvXb X9IduabyvHy8vQRZsqlE9lTiOOOC9jwh27TXsD05HAXmNYiR6voekzEvfS88vnot 2QIDAQAB -----END PUBLIC KEY-----</Key> </OAuthKeyConfiguration> <OAuthKeyConfiguration> <KeyId>03b2d22c2fecf873ed19e5b8cf704afb7e2ed4be</KeyId> <Algorithm>RSA</Algorithm> <Key>-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArKZ+1zdz/CoLekSynOty Wv6cPSSkV28Kb9kZZHyYL+yhkKnH/bHl8OpWiGxQiKP0ulLRIaq1IhSMetkZ8FfX H+iptIDu4lPb8gt0HQYkjcy3HoaKRXBw2F8fJQO4jQ+ufR4l+E0HRqwLywzdtAIm NWmju3A4kx8s0iSGHGSHyE4EUdh5WKt+NMtfUPfB5v9/2bC+w6wH7zAEsI5nscMX nvz1u8w7g2/agyhKSK0D9OkJ02w3I4xLMlrtKEv2naoBGerWckKcQ1kBYUh6WASP dvTqX4pcAJi7Tg6jwQXIP1aEq0JU8C0zE3d33kaMoCN3SenIxpRczRzUHpbZ+gk5 PQIDAQAB -----END PUBLIC KEY-----</Key> </OAuthKeyConfiguration> </OAuthKeyConfigurations> <Enabled>true</Enabled> <ClientId>**redacted**.apps.googleusercontent.com</ClientId> <ClientSecret>**redacted**</ClientSecret> <UserAuthorizationEndpoint>https://accounts.google.com/o/oauth2/v2/auth</UserAuthorizationEndpoint> <AccessTokenEndpoint>https://oauth2.googleapis.com/token</AccessTokenEndpoint> <UserInfoEndpoint>https://openidconnect.googleapis.com/v1/userinfo</UserInfoEndpoint> <Scope>email profile openid</Scope> <OIDCAttributeMapping> <SubjectAttributeName>email</SubjectAttributeName> <EmailAttributeName>email</EmailAttributeName> <FirstNameAttributeName>given_name</FirstNameAttributeName> <LastNameAttributeName>family_name</LastNameAttributeName> <GroupsAttributeName>groups</GroupsAttributeName> <RolesAttributeName>roles</RolesAttributeName> </OIDCAttributeMapping> <MaxClockSkew>600</MaxClockSkew> </OrgOAuthSettings> [/code]