# Sync DiscourseConnect user data with the sync\_sso route

**URL:** https://meta.discourse.org/t/sync-discourseconnect-user-data-with-the-sync-sso-route/84398
**Category:** Integrations
**Tags:** sso, rest-api, tutorial
**Created:** [April 2, 2018, 6:43pm UTC](https://meta.discourse.org/t/sync-discourseconnect-user-data-with-the-sync-sso-route/84398 "2018-04-02T18:43:17Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![Discourse](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/discourse/32/148734_2.png) [@Discourse](https://meta.discourse.org/u/Discourse)
#### Post date: [April 2, 2018, 6:43pm UTC](https://meta.discourse.org/t/sync-discourseconnect-user-data-with-the-sync-sso-route/84398/1 "2018-04-02T18:43:17Z")

</div>

Single Sign On can be used to handle Discourse user authentication from a separate site. The [Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso)](https://meta.discourse.org/t/official-single-sign-on-for-discourse-sso/13045) topic has details about how to implement [DiscourseConnect](https://meta.discourse.org/t/13045?silent=true) .

### The Problem

With [DiscourseConnect](https://meta.discourse.org/t/13045?silent=true) , Discourse users will be created or updated when they login to Discourse from your external website. What it doesn’t handle is when you need to create or update Discourse users without having them login to your site. For sites that are using [DiscourseConnect](https://meta.discourse.org/t/13045?silent=true) , these cases should be handled by making an authenticated `POST` request to the `sync_sso` route.

> _ℹ If you are using the Discourse API gem, you can use the gem’s `sync_sso` method instead of using the following code. See the [examples](https://github.com/discourse/discourse_api/blob/master/examples/sso.rb) directory for instructions on how to use the method._

As an example, we’ll take a case where a user is added to a group on the parent site, and they need to be added to a corresponding group on Discourse without having to first login with [DiscourseConnect](https://meta.discourse.org/t/13045?silent=true) . The name of the group on both the website and the forum is ‘eurorack’. The `external_id` of the user is `1` and their email is `bob@example.com`. The following code is using `PHP`. The basic idea can be applied to any programming language.

### Setup your API credentials and SSO secret key

```plaintext
$api_key = '4fe83002bb5fba8c9a61a65e5b4b0a3cf8233b0e4ccafc85ebd6607abab4651a';
$api_username = 'system';
$discourse_connect_secret = 'jdhb19*Xh3!nu(#k';

```

### Setup the sso parameters

To see what parameters are available, have a look at the `ACCESSORS` section of [discourse\_connect\_base.rb](https://github.com/discourse/discourse/blob/main/lib/discourse_connect_base.rb#L13-L43). The parameter that you _must_ include to update an existing user is `external_id`. If you are calling `sync_sso` for a user who does not yet exist on Discourse, you must include the `username` and `email` parameters. Discourse will use the `username` and `email` to create a new user.

To add a user to a group, include the `add_groups` parameter. To remove a user from a group, include the `remove_groups` parameter. The value for either of these parameters needs to be set to a comma separated string of group names. _Spaces are not allowed between the group names._

> _ℹ The `require_activation` parameter is being included in the payload. This should be set to `true` if the user’s email hasn’t been validated on the parent site. With `PHP` the parameter needs to be set to the string ‘true’ to avoid it being converted to the number `1`. If you have validated the user’s email address, you do not need to include this parameter._

```plaintext
// Create an array of SSO parameters.
$sso_params = array(
    'external_id' => 1,
    'email' => 'bob@example.com',
    'username' => 'bob',
    'add_groups' => 'eurorack',
    'require_activation' => 'true',
);

// Convert the SSO parameters into the SSO payload and generate the SSO signature.
$sso_payload = base64_encode( http_build_query( $sso_params ) );
$sig = hash_hmac( 'sha256', $sso_payload, $discourse_connect_secret );

```

### Send the POST request

For this example I’ll use `curl`, set the `user_agent` to ‘WordPress/4.9.4’, and the forum URL to `https://forum.example.com`

```plaintext
$url = 'https://forum.example.com/admin/users/sync_sso';
$post_fields = array(
    'sso' => $sso_payload,
    'sig' => $sig,
);
$headers = array("Content-Type: multipart/form-data;","Api-Key: $api_key","Api-Username: $api_username",);

$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, 1 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $post_fields ) );
curl_setopt( $ch, CURLOPT_USERAGENT, 'WordPress/4.9.4' );

$result = curl_exec( $ch );

if ( curl_errno( $ch ) !== 0 ) {
    // Handle error, call curl_close( $ch ) and return.
}

curl_close( $ch );

$discourse_user = json_decode( $result );

```

### Updating existing users

Requests made to the `sync_sso` route will update properties for existing users in the same way as would happen if the user logged into the site with [DiscourseConnect](https://meta.discourse.org/t/13045?silent=true) . That means that the values of your site’s `auth overrides` and `discourse connect overrides` site settings will be respected for these requests. For example, to update the email address for existing users with requests to `sync_sso`, the `auth overrides email` setting needs to be enabled. Here are the relevant settings:

- `auth overrides email`
- `auth overrides username`
- `auth overrides name`
- `discourse connect overrides avatar`
- `discourse connect overrides bio`
- `discourse connect overrides groups`
- `discourse connect overrides profile background`
- `discourse connect overrides card background`
- `discourse connect overrides location`
- `discourse connect overrides website`

### Further Reading

To see what is going on, have a look at the [sync\_sso code](https://github.com/discourse/discourse/blob/main/app/controllers/admin/users_controller.rb#L467), the `DiscourseConnectBase` [parse](https://github.com/discourse/discourse/blob/main/lib/discourse_connect_base.rb#L84) method, and the `DiscourseConnect` [lookup\_or\_create\_user](https://github.com/discourse/discourse/blob/main/app/models/discourse_connect.rb#L100) method.

There is also a [JavaScript edition](https://meta.discourse.org/t/sync-discourseconnect-user-data-with-the-sync-sso-route-javascript/260841) of this guide for those using Node.js.

> Last edited by @MarkDoerr 2025-09-26T16:25:28Z
> 
> > **Check document**
> >
> > Perform check on document:

---

<div class="post-metadata">

### Author: ![river](https://avatars.discourse-cdn.com/v4/letter/r/76d3ee/32.png) [@river](https://meta.discourse.org/u/river)
#### Post date: [May 7, 2024, 6:26am UTC](https://meta.discourse.org/t/sync-discourseconnect-user-data-with-the-sync-sso-route/84398/36 "2024-05-07T06:26:16Z")

</div>

Getting this message: {“failed”:“FAILED”,“message”:“Login Error”}
