Tweaks the text, adds a design remark about SQL functions and adds the token TTL in HTTP cache headers

This commit is contained in:
Diogo Biazus
2015-12-20 14:45:22 -05:00
parent 1d848b8d72
commit eef4e3c647
+29 -13
View File
@@ -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();
```
<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
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})