/admin/users/sync_sso ... Route not found


Any idea why I’m getting this when trying to issue a POST request?

ActionController::RoutingError (No route matches [POST] “/admin/users/sync_sso”)


(Rafael dos Santos Silva) #2

Well the route is that one.

Are you passing api_username and api_key as query params too?


I am. Here is the code block. This is the exact say thing I’m doing in my SSO login route. Only difference is obviously the URI.

     const sso = new DiscourseSSO(SSOKey);
            const nonce = 'dummy data';
            const userparams = {
              external_id: user._id.toString(),
              email: user.email,
              username: user.username.replace(/\s/g, ''),
            const q = sso.buildLoginString(userparams);
            fetch('https://community.testsite.com/admin/users/sync_sso', { method: 'POST', body: q })
              .then(res => res.json())
              .then(json => console.log(json));

(Rafael dos Santos Silva) #4

You aren’t passing api_username and api_key.

You need those as query params.

You can check our #howto in the topic here: Sync SSO user data with the sync_sso route


sso.buildLoginString is doing that.

discourse_sso.prototype.buildLoginString = function(params) {
	if(!("external_id" in params)) {
		throw new Exception("Missing required parameter 'external_id'");
	if(!("nonce" in params)) {
		throw new Exception("Missing required parameter 'nonce'");
	if(!("email" in params)) {
		throw new Exception("Missing required parameter 'email'");
	var payload = new Buffer( querystring.stringify(params) , 'utf8').toString("base64");
	var hmac = this.getHmac();
	return querystring.stringify({
		'sso': payload,
		'sig': hmac.digest('hex')

Using this node package for SSO login. Which works perfectly. Trying to repurpose that for this …

(Rafael dos Santos Silva) #7

Where? I don’t see api_username and api_key anywhere.


Right. I was adding in as form data before. Here is the updated. Still getting the Route Not Found error in the rails logs though.

 const userparams = {
          api_username: someusername,
          api_key: somekey,
          external_id: user._id.toString(),
          email: user.email,
          username: user.username.replace(/\s/g, ''),


Code that produces the bottom query:

const userparams = {
      external_id: user._id.toString(),
      email: user.email,
      username: user.username.replace(/\s/g, ''),
    const payload = new Buffer(querystring.stringify(userparams), 'utf8').toString('base64');
    const hmac = crypto.createHmac('sha256', DiscourseSSOKey);
    const query = querystring.stringify({
      sso: payload,
      sig: hmac.digest('hex'),
      api_username: UserName,
      api_key: API Key,
    fetch('https://community.somesite.com/admin/users/sync_sso', {
      method: 'POST',
      body: query,
      .then(res => res.json())
      .then(json => console.log(json));    

Here’s the query that gets generated and passed as the body on the POST route:


This all still gives me a Route Not Found error in the rails logs.


Any thoughts on the above? Does that look right?

(Kane York) #11

You’re delivering the wrong Content-Type. Try providing the object directly as the body to fetch, without querystring.stringify.

also, hang on a sec, i’m going to let you finish, but URLSearchParams is the best browser api of 2016

(Michael Brown) #12

The api_* parameters need to be in the query parameters, not the POST body.

So you need something like:

fetch('https://community.testsite.com/admin/users/sync_sso?api_username=USERNAME&api_key=KITTENS', { method: 'POST', body: body })


Ah understood. So the api_username and api_key in the query parameters and the rest in the post body.

(Blake Erickson) #14

They can also be in the body

All my Postman requests have them in the body:

Unless this route is special?

(Simon Cossar) #15

It’s not. The WordPress plugin sends the api parameters for the sync_sso route in the body of the request: wp-discourse/discourse-sso.php at master · discourse/wp-discourse · GitHub

(Kane York) #16

That’s correct, the problem was sending the wrong body type so the api_username/api_key couldn’t be parsed out.

(shahid) #17


I am attemping the SSO sync but getting the no route found error. Im trying via postman.
I have tried adding the key and username both in the body and as request params, but same result.

any ideas?

(shahid) #18

could you elaborate on this… if using postman, what headers/values need to be set?

(Blake Erickson) #19

The Content-Type should be “multipart/form-data”, but I don’t think you have to set that in the header if the Body is already set to “form-data” (my Headers in Postman are all blank).

(shahid) #20

hmmm, theres not much in the logs to highlight where the issue is…
failing that, is it most likely the payload and sig thats the problem?

(shahid) #21

For testing this, im doing the following:

  1. taking the following payload string:

  2. Generating the base64 encoded payload via:

  3. Taking that payload and generating the hmac-Sha256 encryped payload via:
    Free Online HMAC Generator / Checker Tool (MD5, SHA-256, SHA-512) - FreeFormatter.com

  4. Then sticking them both in postman, sso=payload, sig=encrypted payload

  5. I have generated an API key for user ‘system’ and passing that in with the body.

Error i get in discourse logs:

Started POST “/discussion/admin/users/sync_sso” for at 2018-05-24 15:45:08 +0000

ActionController::RoutingError (No route matches [POST] “/admin/users/sync_sso”)

/var/www/discourse/vendor/bundle/ruby/2.4.0/gems/actionpack-5.1.4/lib/action_dispatch/middleware/debug_exceptions.rb:63:in `call’

Rendering text template