My understanding is that after the login, a cookie is stored and the call should return the logged in user’s API key. However the data returned (which is displayed on the page after the redirect) does not do this, it contains only the HTML content of the communities site.
However calling document.cookie only returns the test cookie I set on the page load, and none of the others.
I will need to test this behaviour with other cookies as it may be an issue in Vue - but it appears cookies from other domains are not accessible for some reason.
Cookies are not directly visible to client-side programs such as JavaScript if they have been sent with the HttpOnly flag. From the point of view of the server, the only difference with respect of the normal case is that the set-cookie header line is added a new field containing the string `HttpOnly’:
When the browser receives such a cookie, it is supposed to use it as usual in the following HTTP exchanges, but not to make it visible to client-side scripts. The HttpOnly flag is not part of any standard, and is not implemented in all browsers.
Update from 2017: a lot of time had passed since 2009, and HttpOnly header flag is became a standard, defined in the section 5.2.6 of RFC6265, with the storage semantics described in the same document (look for “http-only-flag” throughout the RFC text).
There is no way to access anything about the HttpOnly cookies from “non-HTTP” APIs, e.g. JavaScript. By design, neither reading, nor writing such cookies is possible
Did you make sure the Discourse server indeed sent a header “Set-Cookie: ... ; HttpOnly” to set the cookie? You can see that when analyzing the server’s response in the browser’s web developer tools.
In the Firefox web developer tools, the cookie list shows a column “HttpOnly”, and that is true for the _t cookie, which is the relevant one for login. (The _forum_session is for something else.) So yes, the cookie uses HttpOnly
Could you try setting HttpOnly to false for that cookie (works by editing the column in the cookie list, at least in the Firefox web developer tools). And then see if it solves the issue with your script.
I had expected that the relevant cookies will be automatically appended by the browser to any requests sent to communities.edgeryders.eu, including when sending the requests by JavaScript.
But I didn’t have to deal with cookies in cross-site scripting applications before. Maybe these cookies are just not appended to the request by the browser in such a case? And also not visible to scripts because they belong to a different domain? (Ah, actually they might not be accessible because now your script is on a domain that is not an edgeryders.eu subdomain. You can try.)
Probably you’ll have to read up on cookie handling in cross-site applications to figure out what’s not working right now. Sorry for the mess …
I’ll do a bit of reading and see what I can find out, but from a brief glimpse on StackOverflow there seem to be multiple issues with (1) httpOnly cookies and (2) sharing cookies across domains…
There is the so-called Discourse User API Key mechanism to authenticate external applications for using somebody’s user account in Discourse. We did not use it before because authenticating them is complex given our setup (login to communities.edgeryders.eu, then login to edgeryders.eu, then confirm app access, then return). But if nothing else works, we should try that because it’s the solution prepared for these use cases.
I guess you probably know which solution is more ideal… if that authentication process is only required once per user, it wouldn’t be so bad - although perhaps not intuitive to a user.
another idea would be to have a small server side application with a master API key to create posts on behalf of a user, something like this would not be too difficult to implement:
user logs in via SSO and is redirected to site
site has account user ID, calls small server app with ID parameter
server app posts on behalf of user matching account ID with master API key
it might be another security risk and understand you’re not a fan of more middleware, but it could be the fastest way to get a working solution.
We found this plugin which looks promising and might offer a simple solution to the problem. I’ll install it and check if it works for our requirements.
@Daniel This looks really good - by means of JWT, could a user potentially login from the front end application without redirecting to communities.edgeryders.eu?
Ok, so here’s the solution: @owen, please use the off-the-shelf Discourse User API Key mechanism. Use it to let the user approve access of your application to their edgeryders.eu user account. Which means, the URL to forward them to for approving the application’s access is NOThttps://communities.edgeryders.eu/... but:
https://edgeryders.eu/user-api-key/new
This is the default mechanism provided by Discourse for authenticating external applications. We should not try to roll our own alternative for this, because we’d have to maintain that for years, and we already know that all authentication related customizations easily break during Discourse updates. We spent three hours looking for other alternatives like JWT based authentication, but there is no ready-made solution for Discourse anywhere. So we’ll go with what Discourse provides out of the box.
If the user as an edgeryders.eu account and is logged into it, your application forwards the user to https://edgeryders.eu/user-api-key/new for approving access to their edgeryders.eu account. That takes only a single click, and then the user is forwarded back to your application.
If the user as an edgeryders.eu account but is not logged into it, your application also forwards the user to https://edgeryders.eu/user-api-key/new. From there, the user will be forwarded to communities.edgeryders.eu for login, then back to approve the application, then back to your application. This is obviously annoying, but will happen only in 5% of cases as people typically stay logged in.
You can (and should) save the resulting User-Api-Key value in offline storage into the user’s browser. That way, authenticating the application has only to be done the first time the user uses it.
Thanks @matthias, for the help and work - I will give it a go tomorrow morning.
just to be clear - when I forward to https://edgeryders.eu/user-api-key/new - am I including a url parameter of some kind? how does this work exactly for the redirect…
The User API Key mechanism will not be simple to implement on the client side. But after looking around long enough, it’s the best solution for people holding an account. So take your time to get this right, and let nobody stress you about it Also, you might find a JavaScript library that already implements the client-side functions of this API key mechanism.
Hello @matthias - I’m still in the process of working on the login function, but I have implemented a directory for the forms with support for different fields.