diff --git a/docs/examples/external_auth.md b/docs/examples/external_auth.md index 4c560416e..e9a191ed5 100644 --- a/docs/examples/external_auth.md +++ b/docs/examples/external_auth.md @@ -21,7 +21,7 @@ so I'm assuming that the reader's authentication system is already working. ### Sharing the JWT Secret -To allow a third party to generate valid JWTs for your PostgREST API +Allowing a third party to generate valid JWTs for your PostgREST API is just a matter of sharing a secret. So you need to give your authenticator software the same secret that was used in your API server under the ```--jwt-secret``` parameter. @@ -42,11 +42,11 @@ I'll add a text field called role to my users table: ALTER TABLE users ADD role text NOT NULL DEFAULT 'customer'; ``` -For our example we will need besides the main user that PostgREST uses to connect to PostgreSQL -and the anonymous user, we will have two aditional roles: +Besides the main user that PostgREST uses to connect to PostgreSQL +and the anonymous user, we will need two aditional roles for our example: -* admin - to be used by users where admin = true -* customer - to be used where admin = false +* admin - to be used by users that access all the system rows. +* customer - to be used when user has restricted access to database rows. Bellow we have the commands to create all roles that will be used: ```sql @@ -55,7 +55,7 @@ CREATE ROLE anonymous; CREATE ROLE admin; CREATE ROLE customer; -GRANT customer, admin, anonymous TO postgrest; +GRANT customer, admin, anonymous TO authenticator; ``` ### Generating a JWT @@ -75,6 +75,8 @@ For this I just open a file ```app/controllers/api_tokens_controller.rb``` with ```ruby class ApiTokensController < ApplicationController + TOKEN_TTL = 1.hour + def show unless ENV['JWT_SECRET'].present? return render json: {error: "you need to have JWT_SECRET configured to get an API token"}, status: 500 @@ -84,6 +86,7 @@ class ApiTokensController < ApplicationController return render json: {error: "only authenticated users can request the API token"}, status: 401 end + expires_in TOKEN_TTL, public: false render json: {token: jwt}, status: 200 end @@ -93,10 +96,12 @@ class ApiTokensController < ApplicationController end def claims - # I'm assuming a boolean field admin in the user model indicating wheter the - # user has administrative privileges. # This token will expire 1 hour after being issued - { role: current_user.role, user_id: current_user.id.to_s, exp: (Time.now + 1.hour).to_i } + { + role: current_user.role, + user_id: current_user.id.to_s, + exp: (Time.now + TOKEN_TTL).to_i + } end end ``` @@ -113,8 +118,9 @@ whose value is the token the API requests should use. ### Orders Endpoint -Here we describe how to create a view to generate an endpoint /orders filtered by -the logged in user. +Here is how to create a view to generate an endpoint ```/orders``` filtered by +the logged in user: + ```sql ALTER DATABASE mydb SET postgrest.claims.user_id TO ''; @@ -144,10 +150,20 @@ WHERE current_user = 'admin' OR o.user_id = current_user_id(); ``` +
+

DRY priviledge checking conditions

+

+ You can encapsulate conditions that will be commonly used to check for privileges while reading a database row. + We used a function current_user_id() but we could add more conditions to functions + as the system becomes more complex.
+ Remeber to mark your functions as STABLE so that PostgreSQL can inline then while planning the query. +

+
+ ### Using the JWT -Now any page generated by our Rails app, after we are authenticated we can use a simple -Javascript code to get our token and use it: +Now whenever you are authenticated in your Rails application you can use some Javascript + code to get the token and use it: ```javascript $.getJSON('/api_json').done(function(data){ $.ajax('/orders', {'Authorization': 'Bearer ' + data.token})