OAuth 2.0 - HL Vanilla Community
<main> <article class="userContent"> <p><strong>Higher Logic Vanilla</strong> (<strong>Vanilla</strong>) provides tailored OAuth 2.0 integrations with these third-party identity providers as ready-to-go addons:</p><ul><li>Facebook</li><li>Twitter</li><li>LinkedIn</li><li>Google+</li></ul><p><strong>📝 NOTE</strong>: To learn how to use these SSO methods, check out <a href="https://success.vanillaforums.com/kb/articles/36" rel="nofollow noreferrer ugc">this article</a>.</p><p>We also provide a generic OAuth2 addon that works with basic implementations, including support for the third-party service Auth0.</p><p>Because OAuth 2.0 is an SSO <em>framework</em> and not a narrowly defined protocol (see <a href="https://tools.ietf.org/html/rfc6749" rel="nofollow noreferrer ugc">OAuth 2.0 Spec</a>), custom services work is occasionally required to set up an OAuth solution tailored to your community. Our generic OAuth2 addon is highly extensible so it can render these services quickly and efficiently.</p><p>If you do not currently have an OAuth 2.0 identity provider, we strongly recommend using a third-party provider in place of creating a new one before launching your community.</p><p>Vanilla supports the <strong>authorization code grant </strong>workflow. You will not be able to use the <em>implicit grant flow</em> without creating a custom plugin. To learn about the differences between these two methods for OAuth 2.0, read <a href="https://developer.okta.com/blog/2018/05/24/what-is-the-oauth2-implicit-grant-type" rel="nofollow noreferrer ugc">this article.</a></p><h2 data-id="use-the-oauth2-addon-in-vanilla">Use the OAuth2 addon in Vanilla</h2><p>As with all our SSO solutions, OAuth2 accounts are mapped to existing community accounts by email address, or a new account is created if no match is found. You may combine it with any other SSO connections.</p><p>A settings form in the Dashboard allows you to define custom parameter names for:</p><ul><li>Client id</li><li>Client secret</li><li>Full path to the: <ul><li>authorization URI, </li><li>registration URI, </li><li>sign out URI, </li><li>token endpoint, and </li><li>profile endpoint</li></ul></li><li>Scope</li><li>Expected keys in the JSON response to the profile request</li></ul><h3 data-id="map-user-profile-values">Map user profile values</h3><p>The Profile endpoint, or user-info endpoint, is expected to return a JSON-encoded array of the user's data (<a href="https://success.vanillaforums.com/kb/articles/248-oauth2-addons#assumptions" rel="nofollow noreferrer ugc">view this article for the expectations</a>)<a href="https://success.vanillaforums.com/kb/articles/248-oauth2-addons#assumptions" rel="nofollow noreferrer ugc">.</a> The Profile URL field is required in the OAuth2 addon: Vanilla does not support getting user data from an IDToken.</p><p>The OAuth2 workflow sends the user's profile data as a set of key/value pairs in a JSON object. If those key names do not correspond to Vanilla's, you will need to map the key names in the OAuth2 addon Settings form. For example, if your authentication provider sends the user's profile like this:</p><pre class="code codeBlock" spellcheck="false" tabindex="0">{ "address": "dave@email.com", "pic": "https://cdn.aws.com/ourcdn/davesprofilepic.gif", "name": "Dave", "fullname": "Dave Johnson", "id": 1828838378 } </pre><p>You will need to configure the dashboard accordingly:</p><div class="embedExternal embedImage display-large float-none"> <div class="embedExternal-content"> <a class="embedImage-link" href="https://us.v-cdn.net/6030677/uploads/351/WILTDOMH3GCD.png" rel="nofollow noreferrer noopener ugc" target="_blank"> <img class="embedImage-img" src="https://us.v-cdn.net/6030677/uploads/351/WILTDOMH3GCD.png" alt="Screen Shot 2019-05-22 at 3.06.27 PM.png" height="708" width="1520" loading="lazy" data-display-size="large" data-float="none"></img></a> </div> </div> <p>The OAuth2 plugin even supports multi-dimensional responses. If your authentication provider's user profile response looks like this:</p><pre class="code codeBlock" spellcheck="false" tabindex="0">{ "address": "dave@email.com", "pictures": { "preferred": "https://cdn.aws.com/ourcdn/davesprofilepic.gif" }, "name": "Dave", "fullname": "Dave Johnson", "id": 1828838378 } </pre><p>You can map it by using dot-notation:</p><div class="embedExternal embedImage display-large float-none"> <div class="embedExternal-content"> <a class="embedImage-link" href="https://us.v-cdn.net/6030677/uploads/732/1YCSKF8RFYNB.png" rel="nofollow noreferrer noopener ugc" target="_blank"> <img class="embedImage-img" src="https://us.v-cdn.net/6030677/uploads/732/1YCSKF8RFYNB.png" alt="Screen Shot 2019-05-22 at 3.13.25 PM.png" height="680" width="1446" loading="lazy" data-display-size="large" data-float="none"></img></a> </div> </div> <h3 data-id="pass-roles-over-oauth2">Pass roles over OAuth2</h3><p>You can pass a user's role in the profile response. Unlike the values shown above, there is no user interface for mapping the key name for roles in the Dashboard -- <em>yet</em>. For now, if you want to pass a user's role and have it applied as a role in the community, it <strong><em>must </em></strong>be passed as "Roles" (case-insensitive, plural "Roles"). The value can be a comma-separated list of Roles. In order for it to work, it <strong><em>must</em></strong> correspond exactly with name of a Role or Roles configured for your community.</p><p>For example:</p><pre class="code codeBlock" spellcheck="false" tabindex="0">{ "address": "dave@email.com", "pic": "https://cdn.aws.com/ourcdn/davesprofilepic.gif", "name": "Dave", "fullname": "Dave Johnson", "id": 1828838378, "Roles": "Moderator, Cheerleader" } </pre><p>Will assign these two Roles to this user:</p><div class="embedExternal embedImage display-large float-none"> <div class="embedExternal-content"> <a class="embedImage-link" href="https://us.v-cdn.net/6030677/uploads/260/SFXJIJGWSVYN.png" rel="nofollow noreferrer noopener ugc" target="_blank"> <img class="embedImage-img" src="https://us.v-cdn.net/6030677/uploads/260/SFXJIJGWSVYN.png" alt="Screen Shot 2019-05-22 at 3.29.30 PM.png" height="256" width="1850" loading="lazy" data-display-size="large" data-float="none"></img></a> </div> </div> <p>By default, Vanilla will re-assign the user's Roles every time they log in over SSO, giving your authentication provider full control over the user's Roles. Cloud customers who want to assign Roles to users in the Vanilla Dashboard, <em>and </em>have roles <em>added</em> over SSO, can ask support to configure their community to work in this way. For more details on passing Roles over SSO, <a href="https://success.vanillaforums.com/kb/articles/179-managing-roles-with-sso" rel="nofollow noreferrer ugc">check out this article</a>.</p><h3 data-id="%22allow-this-connection-to-issue-api-access-tokens.%22">"Allow this connection to issue API access tokens."</h3><div class="embedExternal embedImage display-large float-none"> <div class="embedExternal-content"> <a class="embedImage-link" href="https://us.v-cdn.net/6030677/uploads/FAVBHMOMQON6/screen-shot-2020-07-10-at-4-45-16-pm.png" rel="nofollow noreferrer noopener ugc" target="_blank"> <img class="embedImage-img" src="https://us.v-cdn.net/6030677/uploads/FAVBHMOMQON6/screen-shot-2020-07-10-at-4-45-16-pm.png" alt="Screen Shot 2020-07-10 at 4.45.16 PM.png" height="146" width="1942" loading="lazy" data-display-size="large" data-float="none"></img></a> </div> </div> <p>To allow Vanilla to access a user's profile data from your authentication provider, you have to send a short-lived access token to Vanilla. You can also use your access token to generate a Vanilla access token for the user so that you can make API calls on behalf of this user against Vanilla. </p><p>Just toggle on "Allow this connection to issue API access tokens." Here is how it works:</p><p>After generating an access token on your Token endpoint (e.g., <code class="code codeInline" spellcheck="false" tabindex="0">/oauth/token</code> ) and passing it to Vanilla, use it to <code class="code codeInline" spellcheck="false" tabindex="0">POST</code> to our <code class="code codeInline" spellcheck="false" tabindex="0">api/v2/tokens/oauth</code> with your unique ClientID to receive an access token that you can now use to perform any actions that the user can. </p><p>A call to:</p><pre class="code codeBlock" spellcheck="false" tabindex="0">curl --location --request POST 'https://dev.vanilla.localhost/api/v2/tokens/oauth' \ --header 'Content-Type: text/plain' \ --data-raw '{ "clientID" : "402d75e6-82a7-4d84-a0b5-e5298e97cacc" "oauthAccessToken" : "Ii6JWFSeGgxIkXk3UIU3HWCGejW6nUZn" }' </pre><p>Will return: </p><pre class="code codeBlock" spellcheck="false" tabindex="0">{ "accessToken": "va.kVH976QqVV9WgI_59HDSj2ffKUBuuLxT.SRsKXw.Ut_vRgN", "dateExpires": "2020-07-11T20:04:25+00:00" } </pre><p><strong>📝 NOTE</strong>: Take note of when this token expires and have a strategy to renew it. For more information, refer to the API v2 / tokens section in your Dashboard.</p><h3 data-id="%22make-this-connection-your-default-signin-method.%22">"Make this connection your default signin method."</h3><p>Check the "<strong>Make this connection your default signin method.</strong>" checkbox in the Settings form to make this the only way to log into your community or create new users. This means:</p><ul><li>When you click the default "Sign In" button it will redirect you to your authentication provider to log in. </li><li>The "Username and Password" or "Registration" forms on the community will no longer be accessible to users. </li><li>Users will <strong>not</strong> be able to edit their profiles on the community.</li><li>You <strong>will</strong> be able to redirect users to a configured end-point after they log out.</li></ul><p><strong>If you have created a user natively in the community</strong> <strong>before setting OAuth2 as the default method for connecting</strong> and need to log in via the "Username and Password" form, you can access it by typing <code class="code codeInline" spellcheck="false" tabindex="0">/entry/password</code> in the address bar of your browser. Also, when you try to connect over SSO, and the system detects that you have user with the same email address in the community, you will be asked to enter the password you created when you created the user. If this becomes problematic, talk to your CSM.</p><h3 data-id="logging-out">Logging out</h3><p>Only if you have checked the "<strong>Make this connection your default signin method.</strong>" option can you configure a URL where you would like to redirect a user when he/she logs out of your community. This URL can be an end-point on your authentication provider that will then log them out of the "parent" system. </p><p><strong>📝 NOTE</strong>: If you choose to not log them out of the authentication provider and the user navigates back to the community and clicks "Sign In," he/she will be automatically logged into the community without having to enter a username and password.</p><p>If you wish to redirect the user back to the community after logging him/her out, append the Sign Out URL with (literally) <code class="code codeInline" spellcheck="false" tabindex="0">?Target={target}</code> and our system will URL-encode the URL of the community and pass it in the Sign Out request on your system as <code class="code codeInline" spellcheck="false" tabindex="0">Target</code>. </p><ul><li>For more log out use-cases<a href="https://success.vanillaforums.com/kb/articles/31-sso-overview#logging-users-out" rel="nofollow noreferrer ugc"> read this article</a>.</li></ul><h3 data-id="troubleshooting-your-oauth2-setup">Troubleshooting your OAuth2 setup</h3><p>If you're not sure what data you're sending or how it's formatted, ask your CSM to turn on logging. Then, you can click the <strong>Event Log</strong> link in the left-hand menu to see the logs. Filter on "Event Name" <strong>sso_logging</strong>, and then scroll down to the bottom of the page to view the filtered logs in either JSON or XML format. Search for "RawProfile" to see what key/value pairs you are sending and compare them to "Profile," what they are being translated to. There will also be helpful error messages here as well.</p><h2 data-id="set-up-your-oauth2-provider">Set up your OAuth2 provider</h2><p>With most SSO providers, you will have four additional requirements:</p><ul><li>Your community must be accessed by users over <code class="code codeInline" spellcheck="false" tabindex="0">https</code>.</li><li>Your community must contact your Authorization Server using <code class="code codeInline" spellcheck="false" tabindex="0">https</code>.</li><li>Your Authorization Server must allowlist the redirect URI (e.g., <a href="https://[forum-domain].com/entry/oauth2" rel="nofollow noreferrer ugc"><code class="code codeInline" spellcheck="false" tabindex="0">https://[community-domain].com/entry/oauth2</code></a>).</li><li>Your Authorization Server MUST receive and return the state token in tact that is passed to it from the community in the authorization request. This is an OAuth2 requirement and a security feature. </li></ul><h2 data-id="seamless-connection-from-your-web-app-to-vanilla">Seamless connection from your web app to Vanilla</h2><p>If you have users logged into your web application and you want to provide a link from your application to your Vanilla application without prompting them to log in again, do the following:</p><ul><li>In the Vanilla Dashboard, under <strong>Settings > Addons > OAuth2</strong>, set the "Prompt" dropdown to either "Consent" or "none."</li><li>In your application, the link you provide from your application to the Vanilla application should be:<ul><li> <code class="code codeInline" spellcheck="false" tabindex="0">https://[your-vanilla-app]/entry/oauth2-redirect</code> if you only have one OAuth2 connection. Or, </li><li><code class="code codeInline" spellcheck="false" tabindex="0">https://[your-vanilla-app]/entry/oauth2-redirect?client_id=[the-client-id-of-your-oauth2-connection]</code> if you have more than one OAuth2 connection. </li></ul></li><li>This will automatically redirect users back to your web application passing the "prompt" parameter. Your web application will detect that the user is already logged in. Your web application will only stop the user if they have not already given consent to share data with your Vanilla app (a step that will only happen the first time the user connects). The user will then be redirected to, and logged into, Vanilla. If the user does not exist in Vanilla, the user will be created and logged in. All of this happens "instantaneously" from the user's perspective.</li></ul><h2 data-id="auto-connect">Auto-connect</h2><p>If you want a user to be able to log in through SSO and connect them with their existing user account in Vanilla, you can. Not all of our settings are accessible through user interface. The auto-connect setting can be set by:</p><ul><li>If you are a <strong>cloud customer</strong>, contact your CSM or Vanilla Support and ask to have Auto-connect turned on.</li><li>If you are <strong>self-hosted</strong>, go into<code class="code codeInline" spellcheck="false" tabindex="0"> /conf/config-defaults.php</code><strong> </strong>and add <code class="code codeInline" spellcheck="false" tabindex="0">$Configuration['Garden']['Registration']['AutoConnect'] = true;</code></li></ul><p><strong>🛑 WARNING</strong>: If your users can change their email addresses on your authentication application without being verified, do not use auto-connect. This could allow them to choose an email address that already exists on the community, which would allow them to log in <em>as </em>that community user.</p><h2 data-id="automate-oauth2-connections-with-javascript">Automate OAuth2 connections with JavaScript</h2><p>This section details how a developer on your team could use JavaScript to automatically forward a user through the OAuth2 SSO process, creating a more seamless experience. It is not required for any service, nor is it generally recommended (it will generate <em>significantly</em> increased traffic against your identity provider). We do not provide this as a service.</p><p>The following instructions will determine if the user is currently signed in to their authentication provider and, if the user is indeed signed in, automatically initiate an SSO login to Vanilla using that authentication provider.</p><h3 data-id="create-a-connection-in-javascript">Create a connection in JavaScript</h3><p>First, make a standard HTTPS GET request to the authentication provider’s authorize endpoint. If you’re using Auth0, this is usually something like <code class="code codeInline" spellcheck="false" tabindex="0">https://[eauth-domain].com/authorize</code>. Use the following parameters:</p><ul><li><code class="code codeInline" spellcheck="false" tabindex="0">response_type: code</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">client_id:ABCDEFG</code> (found in the provider’s application settings)</li><li><code class="code codeInline" spellcheck="false" tabindex="0">redirect_uri: https://[community-domain]/entry/oauth2</code> (required to initiate SSO on Vanilla’s side)</li><li><code class="code codeInline" spellcheck="false" tabindex="0">scope: openid profile email</code> (can be configured in the OAuth2 settings page in Vanilla)</li></ul><p>The result is a URL which, when visited by a user signed in on the authentication provider, will route the user back to Vanilla to begin SSO authentication. If the user already has an account, they can automatically connect or can automatically create a new account. They will be signed in to Vanilla at the end of the request chain. The URL will look something like this: <code class="code codeInline" spellcheck="false" tabindex="0">https://[auth-domain].com/authorize?response_type=code&client_idABCDEFG&redirect_uri=https%3A%2F%2Fc[community-domain].com%2Fentry%2Foauth2&scope=openid+profile+email</code></p><h3 data-id="test-the-connection">Test the connection</h3><ol><li>Sign in at <code class="code codeInline" spellcheck="false" tabindex="0">https://[auth-domain].com</code> (your actual SSO sign in page)</li><li>Visit <code class="code codeInline" spellcheck="false" tabindex="0">https://[community-domain].com</code>. Make sure you are not logged in. Clear your cookies, if necessary.</li><li>Visit the “authorize” link described above.</li><li>You should automatically arrive back at <code class="code codeInline" spellcheck="false" tabindex="0">https://[community-domain].com</code>, but you should now be signed into Vanilla.</li></ol><p>In Vanilla, this can be implemented as JavaScript in your page via the Customize Theme feature or a Pocket. Contact Vanilla Support if you need clarification on these steps.</p><h2 data-id="additional-resources">Additional resources</h2><p>Click the link below to access a video expanding on what you learned in this article.</p><div class="js-embed embedResponsive" data-embedjson="{"body":"For more information, please see:","photoUrl":"https:\/\/us.v-cdn.net\/6030677\/uploads\/GXW21TRYG1JP\/share-imagevanilla-community.jpg","url":"https:\/\/success.vanillaforums.com\/kb\/articles\/474","embedType":"link","name":"OAuth 2 SSO - HL Vanilla Community"}"> <a href="https://success.vanillaforums.com/kb/articles/474" rel="nofollow noreferrer ugc"> https://success.vanillaforums.com/kb/articles/474 </a> </div><p><br></p> </article> </main>