/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”)

Thanks!

Well the route is that one.

Are you passing api_username and api_key as query params too?

2 Likes

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 = {
              nonce,
              external_id: user._id.toString(),
              email: user.email,
              username: user.username.replace(/\s/g, ''),
            };
            console.log(userparams);
            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));

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

2 Likes

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();
	hmac.update(payload);
	
	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 …

https://github.com/ArmedGuy/discourse_sso_node

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

1 Like

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 = {
          nonce,
          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);
    hmac.update(payload);
    const query = querystring.stringify({
      sso: payload,
      sig: hmac.digest('hex'),
      api_username: UserName,
      api_key: API Key,
    });
    console.log(query);
    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:

sso=somelongSSOgenerated.&sig=somelongsignature&api_username=someusername&api_key=someAPIKey

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

Any thoughts on the above? Does that look right?

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

3 Likes

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 })
4 Likes

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

They can also be in the body

All my Postman requests have them in the body:

Unless this route is special?

5 Likes

It’s not. The WordPress plugin sends the api parameters for the sync_sso route in the body of the request: https://github.com/discourse/wp-discourse/blob/master/lib/sso-provider/discourse-sso.php#L329

2 Likes

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

5 Likes

Hi

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?

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

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).

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?

For testing this, im doing the following:

  1. taking the following payload string:
    email=discourse-sso2@gmail.com&external_id=auth0|111111111111233444&require_activation=false

  2. Generating the base64 encoded payload via:
    https://www.base64encode.org/

  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 123.157.28.69 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