Tweaks the text, adds a design remark about SQL functions and adds the token TTL in HTTP cache headers
This commit is contained in:
@@ -21,7 +21,7 @@ so I'm assuming that the reader's authentication system is already working.
|
|||||||
|
|
||||||
### Sharing the JWT Secret
|
### 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
|
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```
|
software the same secret that was used in your API server under the ```--jwt-secret```
|
||||||
parameter.
|
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';
|
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
|
Besides the main user that PostgREST uses to connect to PostgreSQL
|
||||||
and the anonymous user, we will have two aditional roles:
|
and the anonymous user, we will need two aditional roles for our example:
|
||||||
|
|
||||||
* admin - to be used by users where admin = true
|
* admin - to be used by users that access all the system rows.
|
||||||
* customer - to be used where admin = false
|
* 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:
|
Bellow we have the commands to create all roles that will be used:
|
||||||
```sql
|
```sql
|
||||||
@@ -55,7 +55,7 @@ CREATE ROLE anonymous;
|
|||||||
CREATE ROLE admin;
|
CREATE ROLE admin;
|
||||||
CREATE ROLE customer;
|
CREATE ROLE customer;
|
||||||
|
|
||||||
GRANT customer, admin, anonymous TO postgrest;
|
GRANT customer, admin, anonymous TO authenticator;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Generating a JWT
|
### Generating a JWT
|
||||||
@@ -75,6 +75,8 @@ For this I just open a file ```app/controllers/api_tokens_controller.rb``` with
|
|||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
class ApiTokensController < ApplicationController
|
class ApiTokensController < ApplicationController
|
||||||
|
TOKEN_TTL = 1.hour
|
||||||
|
|
||||||
def show
|
def show
|
||||||
unless ENV['JWT_SECRET'].present?
|
unless ENV['JWT_SECRET'].present?
|
||||||
return render json: {error: "you need to have JWT_SECRET configured to get an API token"}, status: 500
|
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
|
return render json: {error: "only authenticated users can request the API token"}, status: 401
|
||||||
end
|
end
|
||||||
|
|
||||||
|
expires_in TOKEN_TTL, public: false
|
||||||
render json: {token: jwt}, status: 200
|
render json: {token: jwt}, status: 200
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -93,10 +96,12 @@ class ApiTokensController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def claims
|
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
|
# 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
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@@ -113,8 +118,9 @@ whose value is the token the API requests should use.
|
|||||||
|
|
||||||
### Orders Endpoint
|
### Orders Endpoint
|
||||||
|
|
||||||
Here we describe how to create a view to generate an endpoint /orders filtered by
|
Here is how to create a view to generate an endpoint ```/orders``` filtered by
|
||||||
the logged in user.
|
the logged in user:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
ALTER DATABASE mydb SET postgrest.claims.user_id TO '';
|
ALTER DATABASE mydb SET postgrest.claims.user_id TO '';
|
||||||
|
|
||||||
@@ -144,10 +150,20 @@ WHERE
|
|||||||
current_user = 'admin' OR o.user_id = current_user_id();
|
current_user = 'admin' OR o.user_id = current_user_id();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<div class="admonition note">
|
||||||
|
<p class="admonition-title">DRY priviledge checking conditions</p>
|
||||||
|
<p>
|
||||||
|
You can encapsulate conditions that will be commonly used to check for privileges while reading a database row.
|
||||||
|
We used a function <code>current_user_id()</code> but we could add more conditions to functions
|
||||||
|
as the system becomes more complex.<br/>
|
||||||
|
Remeber to mark your functions as <code>STABLE</code> so that PostgreSQL can inline then while planning the query.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
### Using the JWT
|
### Using the JWT
|
||||||
|
|
||||||
Now any page generated by our Rails app, after we are authenticated we can use a simple
|
Now whenever you are authenticated in your Rails application you can use some Javascript
|
||||||
Javascript code to get our token and use it:
|
code to get the token and use it:
|
||||||
```javascript
|
```javascript
|
||||||
$.getJSON('/api_json').done(function(data){
|
$.getJSON('/api_json').done(function(data){
|
||||||
$.ajax('/orders', {'Authorization': 'Bearer ' + data.token})
|
$.ajax('/orders', {'Authorization': 'Bearer ' + data.token})
|
||||||
|
|||||||
Reference in New Issue
Block a user