|
1 | 1 | ## discourse-oauth2-basic |
2 | 2 |
|
3 | | -This plugin has now been bundled into Discourse core. See: https://meta.discourse.org/t/bundling-more-popular-plugins-with-discourse-core/373574 |
| 3 | +> [!IMPORTANT] |
| 4 | +> This plugin has now been bundled into Discourse core. See: https://meta.discourse.org/t/bundling-more-popular-plugins-with-discourse-core/373574 |
| 5 | +
|
| 6 | +This plugin allows you to use a basic OAuth2 provider as authentication for |
| 7 | +Discourse. It should work with many providers, with the caveat that they |
| 8 | +must provide a JSON endpoint for retrieving information about the user |
| 9 | +you are logging in. |
| 10 | + |
| 11 | +This is mainly useful for people who are using login providers that aren't |
| 12 | +very popular. If you want to use Google, Facebook or Twitter, those are |
| 13 | +included out of the box and you don't need this plugin. You can also |
| 14 | +look for other login providers in our [Github Repo](https://github.com/discourse). |
| 15 | + |
| 16 | +## Usage |
| 17 | + |
| 18 | +## Part 1: Basic Configuration |
| 19 | + |
| 20 | +First, set up your Discourse application remotely on your OAuth2 provider. |
| 21 | +It will require a **Redirect URI** which should be: |
| 22 | + |
| 23 | +`http://DISCOURSE_HOST/auth/oauth2_basic/callback` |
| 24 | + |
| 25 | +Replace `DISCOURSE_HOST` with the appropriate value, and make sure you are |
| 26 | +using `https` if enabled. The OAuth2 provider should supply you with a |
| 27 | +client ID and secret, as well as a couple of URLs. |
| 28 | + |
| 29 | +Visit your **Admin** > **Settings** > **OAuth2 Login** and fill in the basic |
| 30 | +configuration for the OAuth2 provider: |
| 31 | + |
| 32 | +- `oauth2_enabled` - check this off to enable the feature |
| 33 | + |
| 34 | +- `oauth2_client_id` - the client ID from your provider |
| 35 | + |
| 36 | +- `oauth2_client_secret` - the client secret from your provider |
| 37 | + |
| 38 | +- `oauth2_authorize_url` - your provider's authorization URL |
| 39 | + |
| 40 | +- `oauth2_token_url` - your provider's token URL. |
| 41 | + |
| 42 | +If you can't figure out the values for the above settings, check the |
| 43 | +developer documentation from your provider or contact their customer |
| 44 | +support. |
| 45 | + |
| 46 | +## Part 2: Configuring the JSON User Endpoint |
| 47 | + |
| 48 | +Discourse is now capable of receiving an authorization token from your |
| 49 | +OAuth2 provider. Unfortunately, Discourse requires more information to |
| 50 | +be able to complete the authentication. |
| 51 | + |
| 52 | +We require an API endpoint that can be contacted to retrieve information |
| 53 | +about the user based on the token. |
| 54 | + |
| 55 | +For example, the OAuth2 provider [SoundCloud provides such a URL](https://developers.soundcloud.com/docs/api/reference#me). |
| 56 | +If you have an OAuth2 token for SoundCloud, you can make a GET request |
| 57 | +to `https://api.soundcloud.com/me?oauth_token=A_VALID_TOKEN` and |
| 58 | +will get back a JSON object containing information on the user. |
| 59 | + |
| 60 | +To configure this on Discourse, we need to set the value of the |
| 61 | +`oauth2_user_json_url` setting. In this case, we'll input the value of: |
| 62 | + |
| 63 | +``` |
| 64 | +https://api.soundcloud.com/me?oauth_token=:token |
| 65 | +``` |
| 66 | + |
| 67 | +The part with `:token` tells Discourse that it needs to replace that value |
| 68 | +with the authorization token it received when the authentication completed. |
| 69 | +Discourse will also add the `Authorization: Bearer` HTTP header with the |
| 70 | +token in case your API uses that instead. |
| 71 | + |
| 72 | +There is one last step to complete. We need to tell Discourse what |
| 73 | +attributes are available in the JSON it received. Here's a sample |
| 74 | +response from SoundCloud: |
| 75 | + |
| 76 | +```json |
| 77 | +{ |
| 78 | + "id": 3207, |
| 79 | + "permalink": "jwagener", |
| 80 | + "username": "Johannes Wagener", |
| 81 | + "uri": "https://api.soundcloud.com/users/3207", |
| 82 | + "permalink_url": "http://soundcloud.com/jwagener", |
| 83 | + "avatar_url": "http://i1.sndcdn.com/avatars-000001552142-pbw8yd-large.jpg?142a848", |
| 84 | + "country": "Germany", |
| 85 | + "full_name": "Johannes Wagener", |
| 86 | + "city": "Berlin" |
| 87 | +} |
| 88 | +``` |
| 89 | + |
| 90 | +The `oauth2_json_user_id_path`, `oauth2_json_username_path`, `oauth2_json_name_path` and |
| 91 | +`oauth2_json_email_path` variables should be set to point to the appropriate attributes |
| 92 | +in the JSON. |
| 93 | + |
| 94 | +The only mandatory attribute is _id_ - we need that so when the user logs on in the future |
| 95 | +that we can pull up the correct account. The others are great if available -- they will |
| 96 | +make the signup process faster for the user as they will be pre-populated in the form. |
| 97 | + |
| 98 | +Here's how I configured the JSON path settings: |
| 99 | + |
| 100 | +``` |
| 101 | + oauth2_json_user_id_path: 'id' |
| 102 | + oauth2_json_username_path: 'permalink' |
| 103 | + oauth2_json_name_path: 'full_name' |
| 104 | +``` |
| 105 | + |
| 106 | +I used `permalink` because it seems more similar to what Discourse expects for a username |
| 107 | +than the username in their JSON. Notice I omitted the email path: SoundCloud do not |
| 108 | +provide an email so the user will have to provide and verify this when they sign up |
| 109 | +the first time on Discourse. |
| 110 | + |
| 111 | +If the properties you want from your JSON object are nested, you can use periods. |
| 112 | +So for example if the API returned a different structure like this: |
| 113 | + |
| 114 | +```json |
| 115 | +{ |
| 116 | + "user": { |
| 117 | + "id": 1234, |
| 118 | + "email": { |
| 119 | + "address": "test@example.com" |
| 120 | + } |
| 121 | + } |
| 122 | +} |
| 123 | +``` |
| 124 | + |
| 125 | +You could use `user.id` for the `oauth2_json_user_id_path` and `user.email.address` for `oauth2_json_email_path`. |
| 126 | + |
| 127 | +## Part 3: Test it with Google OAuth 2.0 Server |
| 128 | + |
| 129 | +To test this plugin in your local dev environment you can use Google OAuth 2.0 Server. Follow [this guide](https://support.google.com/cloud/answer/6158849?hl=en) to create new OAuth client id & secret. |
| 130 | + |
| 131 | +- While creating it choose "Web application" as "Application type". |
| 132 | +- Add `http://localhost:3000` in "Authorized JavaScript origins" and `http://localhost:3000/auth/oauth2_basic/callback` in "Authorized redirect URIs" fields. |
| 133 | +- Then add following site settings in your admin panel. |
| 134 | + |
| 135 | +```json |
| 136 | +{ |
| 137 | + "oauth2_enabled": true, |
| 138 | + "oauth2_client_id": "YOUR_PROJECT_CLIENT_ID", |
| 139 | + "oauth2_client_secret": "YOUR_PROJECT_CLIENT_SECRET", |
| 140 | + "oauth2_authorize_url": "https://accounts.google.com/o/oauth2/auth", |
| 141 | + "oauth2_token_url": "https://www.googleapis.com/oauth2/v3/token", |
| 142 | + "oauth2_user_json_url": "https://www.googleapis.com/userinfo/v2/me", |
| 143 | + "oauth2_json_user_id_path": "id", |
| 144 | + "oauth2_json_user_name_path": "name", |
| 145 | + "oauth2_json_user_email_path": "email", |
| 146 | + "oauth2_json_user_avatar_path": "picture", |
| 147 | + "oauth2_email_verified": true, |
| 148 | + "oauth2_scope": "https://www.googleapis.com/auth/userinfo.email" |
| 149 | +} |
| 150 | +``` |
| 151 | + |
| 152 | +That's it! You can check it now in your browser. |
| 153 | + |
| 154 | +Good luck setting up custom OAuth2 on your Discourse! |
| 155 | + |
| 156 | +### Issues |
| 157 | + |
| 158 | +Please use [this topic on meta](https://meta.discourse.org/t/oauth2-basic-support/33879) to discuss |
| 159 | +issues with the plugin, including bugs and feature requests. |
| 160 | + |
| 161 | +### How to run tests |
| 162 | + |
| 163 | +Make sure the plugin has been installed, then from the discourse directory run: |
| 164 | + |
| 165 | +``` |
| 166 | +LOAD_PLUGINS=1 bundle exec rspec plugins/discourse-oauth2-basic/spec/plugin_spec.rb |
| 167 | +``` |
| 168 | + |
| 169 | +### License |
| 170 | + |
| 171 | +MIT |
0 commit comments