Is there a POST or GET /logout URL?


(Daniel Eklund) #1

I am using Discourse as my SSO (and forum, of course).

I want to be able to allow logout from my main application, without requiring the user to go to the forum, click on their avatar and selecting the Logout option.

I traced the network and it seems to be an HTTP DELETE on that username:

Is there no other GET or POST way to call this?

I cannot issued a DELETE from a URL in my site (or as part of a 302 redirect).

I did look into the API method (https://meta.discourse.org/t/discourse-sso-logout/28509/4), but that seems to require installing a gem (I think) on my client application side for using the API key, and my client application is not using Ruby.


(Matt Palmer) #2

Try issuing a POST request to that URL, with a request body setting _method=delete. That probably still works as a hack around browsers not learning to HTTP.


(Daniel Eklund) #3

Am I doing this right?

You can see _method=delete in the POST request.

It’s giving me a 403 back, and yes, I am logged in as “reverend_paco” in my own forum. Is this method/hack no longer supported?


(Matt Palmer) #4

Yeah, looks like it. Bummer.


(Daniel Eklund) #5

just more information:

I’m doing this with a 307 redirect. I noticed there are no cookies being set on the request. Interesting.


(Dean Taylor) #6

If this is user side code - You are missing your csrf-token and user cookies

If this is executed by the server - You are missing api_username and api_key.


(Daniel Eklund) #7

definitely user side… i just noticed the cookies were missing, don’t know why that would be with a redirect… maybe the 307 loses the cookies?


(Dean Taylor) #8

I don’t believe a redirect will work on it’s own - you would still need a CSRF token
… obviously work out why the cookies aren’t there first.


(Daniel Eklund) #9

thanks, do i need a csrf if i am on the same domain but different sub-domain?

My main site is wordadoplicus.com (where i have a logout button and which is not forum related at all)… the forum is installed at the sub-domain forum.wordadoplicus.com.


(Dean Taylor) #10

With some minor exceptions my understanding is that all POST requests are required to pass a CSRF token regardless of their origin domain.

Hell, I could be wrong.

You could probably prove this in your browsers JavaScript console for the actual Discourse install…
… generate a POST request using jQuery / JavaScript.

EDIT: I can confirm that POST with data _method: delete works for /session/{username}

Note that I previously mentioned you could test this in your browser using jQuery post - however you then run into ‘Access-Control-Allow-Origin’ header is present on the requested resource when executing on the parent domain - so not a great way of testing.

However it did prove the request works locally.


(Daniel Eklund) #11

@DeanMarkTaylor, thanks for all of this. Just to clarify, you confirmed that a POST worked with the CSRF token?

I appreciate everyone’s help here thus far.

thanks,
dainel


(Dean Taylor) #12

Only confirmed endpoint accepts the post request.

When I tried it the cookies and csrf included automatically because I had a session open and was using a debug console on the current domain.

You are probably looking at a situation where a browsers default security will prevent the cookies from being included because they are set on the sub-domain.


(Daniel Eklund) #13

Oh goodness gracious. I just discovered that my assumptions about the server-side API were wrong. Thankfully, I can use the API, and will thus be abandoning this client-side attempt.

I had assumed that the Discourse API required the ruby gem because there was some sort of encryption going on. In fact, all you need is the api_key and username. I had assumed that it would be a security risk since people could sniff the api key and then use it later.

I can thus logout a user from my application by using pure web calls.

For those doing erlang, it’s as simple as:

  6 kick_em_out(User) ->
  5     Logout = [<<"https://forum.wordadoplicus.com/session/">>,
  4               User,
  3               <<"?api_key=6a28b548eee3dce8bedd56cd3ac8691dea34f5222ca6c5b5556cc257f2ed2c4e&api_username=">>,
  2               User],
  1     API = iolist_to_binary(Logout),
  0     httpc:request(delete,{binary_to_list(API),[]},[],[]).  

(Daniel Eklund) #14

oops… accidentally published my own API Key :slight_smile: … just regenerated a new one


(Matt Palmer) #15

Hence why TLS is such a good idea. No different to a session cookie, either.

Good to see some Erlang code again.


(Sam Saffron) #16

I do hope you did not expose your API key here :slight_smile:


(Daniel Eklund) #17

silly me. like storing an AWS secret key in github


(Jeff Atwood) #18

seeeeeeeeeeecreeeettttsss :spy: