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.
Could you add these domains
to the whitelist for both edgeryders.eu and http://communities.edgeryders.eu/ ?
Sure. Both done now.
It’s a setting where I have to enter URLs that are allowed as user API auth redirect targets. So I entered these two, hope that’s ok:
http://tell.edgeryders.eu/auth_redirect
https://tell.edgeryders.eu/auth_redirect
Good news - I have the login flow working on the front end, and have tested the post to platform using the User-Api-Key
and it works.
The last issue is with the auth_redirect
parameter. While it works as @matthias set it up, the redirect has to go to the correct url of the form:
For form 14210
this means not to the root domain but Edgeryders Forms
I am not sure if this is possible, as the form urls are dynamically generated. I’m looking into a way of storing the form ID in the payload that is returned instead, and loading the form this way.
The other more minor issue is the json key pair generated on page load - for some reason (way beyond my area of knowledge) it’s fairly slow to generate a key pair in javascript with RSA encryption that works with Discourse. I’m looking to store this as a static value in the .env file to make it faster.
update - @matthias it looks like the “allowed user api auth redirects” setting might support a wildcard in the url, there was a pull request mentioned here. This would solve the first problem if it works.
Good news again
I’ve solved the problem by setting the nonce
parameter as the topic_id
of the form, which is then included in the returned payload and loads the correct form.
It now works, hurrah - http://tell.edgeryders.eu
The last remaining feature to implement is to save the user_api_key
in local storage so users don’t have to re-authenticate again.
In general terms, this is how it works:
- A private RSA key is read from the .env file
- The application generates a public key from this, which is included in a url parameter (along with api scopes, nonce, redirect url) to the endpoint
https://edgeryders.eu/user-api-key/new
- When the user is sent to this url and authenticates, Discourse sends a payload encrypted with the public key back to the application
- The application decrypts the payload containing the user API key (using the private key) which is then used to post the topic to the platform
It sounds a bit simple, but it was a pretty long and windy road to get it working. The upshot of this is it can be used now for many other purposes, we’ve got a working solution for interfacing with the platform from a front end application.
I have also published documentation for anyone who needs to set up a form here.
Great work, that indeed gives us many new options of interacting with the platform!
Yes, this should work as the wildcard syntax is also mentioned in the field explanations. So I have changed the setting now to the following:
https://tell.edgeryders.eu/*
http://tell.edgeryders.eu/*
I think that does not work out as intended. Because I get the following error message with a Server Error 500 on edgeryders.eu/user-api-key after trying to authenticate the application at tell.edgeryders.eu:
ActiveRecord::RecordNotUnique (
PG::UniqueViolation:
ERROR: duplicate key value violates unique constraint "index_user_api_keys_on_client_id"
DETAIL: Key (client_id)=(w02UgniowwfO3sfjbl-pwWwQn0NyJ4xhGi2p_wCD) already exists.
)
My guess is that with the same initial private key, Discourse will see the same client ID, which will be generated from the private key somehow. So I think there is not really a way around the RSA key generation delay, but you can start with that right when the page loads while distracting the user with other things for 5-10 seconds.
Ah I see - yes it works with my account and not yours as I guess the key must be unique. I will test it with the prior solution.
In fact this is not an issue with generating the key pair, but generating a random client_id, so performance should not be affected.
Login to tell.edgeryders.eu with my edgeryders.eu account is confirmed to work now
I’m still not sure that storing the private key is a good idea. It is used to encrypt the data sent later to edgeryders.eu for the User-Api key generation, so “somebody” could listen to that communication and modify it. But then again, if everything is again SSL encrypted via HTTPS, they can’t. But if so, what would this additional layer of encryption exist at all – just for Discourse sites that might not use HTTPS? I don’t know enough about the details of this cryptographic mechanism to make a call, and out of caution would probably not store the key. Or at least ask on meta.discourse.org what the consequences of that would be.
I’m not sure… I think an additional layer of security?
The alternative is to generate a new random key pair each time, but then we run into a technical hurdle (beyond performance): when the user is redirected back to the application a new key pair is generated, so it will be impossible to decrypt the payload since it was encrypted from a previous key pair (on first load). I tested it and it just doesn’t work…
For now it is stored in an .env file, and not in the code itself - so I’m not sure what more can be done to make it secure. But front end cryptography is really not a domain I have much experience or knowledge about…
I propose you look for an answer on meta.discourse.org. If that does not bring new insights, you could also look for an answer in other implementations of the Discourse User-Api key mechanism. And if that does not help, just ask on meta.discourse.org what might be the consequences, security-wide, of storing the initial private key. People there are very helpful Since it’s quite technical, @mention the author of the User-Api key mechanism.
Would be great to get this right so we can rely on this mechanism also when it’s about Discourse accounts with more sensitive data next time.
Hey @matthias - could you also add https://live.edgeryders.eu to the http://communities.edgeryders.eu/ whitelist?
If you can use the wildcard syntax for the auth redirect URL - so it would be:
and results in Edgeryders…
Thanks!
Ok, I have now changed the “allowed user api auth redirects” setting on communities.edgeryders.eu to include the following:
http://live.edgeryders.eu/*
https://live.edgeryders.eu/*
Why do you want it on communities.edgeryders.eu though, and not on edgeryders.eu? That will give the authenticated applications only permission to do something on communities.edgeryders.eu, and there is nothing to do there …
Yes, sorry I mean - https://edgeryders.eu.
The same configuration as tell.edgeryders.eu, but for live.edgeryders.eu that allows a redirect to the application from the communities site.
Ok, done. So I have now reversed the config changed on communities.edgeryders.eu and instead changed the “allowed user api auth redirects” setting on edgeryders.eu to include the following:
http://live.edgeryders.eu/*
https://live.edgeryders.eu/*
Ok - thanks @matthias.
There’s a call about the forms with @MariaEuler and @nadia tomorrow at 12pm - would you be able to join? The reason being there will be some questions about the authorisation page (when logging in) which I won’t be able to answer.
issues to change:
1. Change the Authorization text.
(will be added here and send to Matthias first thing after lunch)
2. Change the language in the field question:
What’s your field?
We don’t expect you to fit into any one category, but if you were to best describe your area of expertise, what would it be?
Domain Expert,
I’m in Policy
I’m in Politics
Tech insider,
Investor,
Entrepreneur or Investor
Activist
Academic/Researcher
Press/Media
other
3. Add creation of post and redirection to it on the platform for the answers part of the step by step guide for the forms
4. Nice to have, but not necessary: Ability to add more logos.
Notes on how to use the form (will be added in manual later):
- Do not ask for name and email again in the form.
- Smal detail note for how to use the form: The role of the form is to be a first point of entry to new or sporadic community members. Therefore description of the event should be added on the top.
- Participant Info sheet needs to be added in each event post from the beginning
- The form generates posts under a post for the event. Everyone who posts in that thread, through the form or directly will get a pm and maybe also email with the zoomlink for the event and the info to not share the zoomlink, but if they want to invite someone else to share the form link.