Get token and docs (#236)

* refactor(auth): change token endpoint from HTTP POST to GET

* ci(docs): trigger publish docs when changes are done to the examples directory

* docs(auth): login, mfa, jwt
This commit is contained in:
Pilou
2020-05-17 09:11:45 +00:00
committed by GitHub
parent f7b2f7d17a
commit b22452243e
6 changed files with 99 additions and 4 deletions

View File

@@ -4,6 +4,7 @@ on:
branches: [master]
paths:
- 'docs/**'
- 'examples/**'
jobs:
deploy:
runs-on: ubuntu-latest

View File

@@ -9,3 +9,6 @@
- server: Updated change password routes for concistency with change email (#235)
- docs: Added API documentation (#235)
- other: Added CHANGELOG.md file (#235)
- refactor(auth): change token endpoint from HTTP POST to GET
- ci(docs): trigger publish docs when changes are done to the examples directory
- docs(auth): login, mfa, jwt

View File

@@ -14,7 +14,7 @@
| ^^ | [POST /auth/change-email/](#) | Change email (without email verification) |
| ^^ | [POST /auth/change-email/request](#) | Request email change |
| ^^ | [POST /auth/change-email/change](#) | Change email |
| ^^ | [POST /auth/token/refresh](#refresh-token) | Get new refresh token |
| ^^ | [GET /auth/token/refresh](#refresh-token) | Get new refresh token |
| ^^ | [POST /auth/token/revoke](#revoke-refresh-token) | Revoke tokens |
| ^^ | [POST /auth/mfa/generate](#generate-mfa-qr-code) | Generate MFA QR code |
| ^^ | [POST /auth/mfa/enable](#enable-mfa) | Enable MFA |

View File

@@ -71,18 +71,86 @@ By default, anyone can register with an email address and a password:
curl -d '{"email":"real@emailadress.com", "password":"StrongPasswordNot1234"}' -H "Content-Type: application/json" -X POST http://localhost:3000/auth/register`
```
You can however add some safeguards and limitations to the registration process like email verification, constraints on emails and passwords, or setting additional registration fields from your custom database schema. More information is available in the [registration configuration chapter](configuration.md#registration).
You can add some safeguards and limitations to the registration process like email verification, constraints on emails and passwords, or setting additional registration fields from your custom database schema. More information is available in the [registration configuration chapter](configuration.md#registration).
## Login
Once an user is registered, they can connect to HBP with the `/auth/register` endpoint:
```shell
curl -d '{"email":"real@emailadress.com", "password":"StrongPasswordNot1234"}' -H "Content-Type: application/json" -X POST http://localhost:3000/auth/register`
```
It will return the following payload:
```json
{
"jwt_token": "<the user Hasura-compatible JWT>",
"jwt_expires_in": "<the number of milliseconds of validity of the JWT>"
}
```
You'll find more details about how HBP handles the session and JWT in the [JWT section](#jwt).
## Multi-Factor Authentication
By default, any authenticted user can decide to add [TOTP](https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm) multi-factor authentication (MFA). It will require the user to get a generator such as [Authy](https://authy.com/) or [Google Authenticator](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en).
### Generate
The first step to activate MFA is to generate a secret through the `/auth/mfa/generate` POST endpoint:
```shell
curl -H "Content-Type: application/json" -X POST http://localhost:3000/auth/mfa/generate`
```
It will return the following payload:
```json
{
"otp_secret": "<the otp secret>",
"image_url": "<the base64-encoded QR Code png image>"
}
```
The client now goes to its favorite MFA app (e.g. Google Authenticator) and enters its secret either manually or in using the QR-code generated by the server.
### Enable
Once the user fetched their OTP secret, they must generate a verification code and send it to HBP to complete the activation or MFA. The code is send to the `/auth/mfa/enable` POST endpoint:
```shell
curl -d '{"code":"<verification-code>"}' -H "Content-Type: application/json" -X POST http://localhost:3000/auth/mfa/enable`
```
The server should return a `204` HTTP code. The user login will now have an additional step as explained in the following section.
### Login
When an user enabled MFA, they still send their user/email credentials to `/auth/login`, but the payload will now become:
```json
{
"mfa": true,
"ticket": "<an automatically one-time only generated ticket>"
}
```
The next step to finish the authentication is to send back the ticket with the verification code from your favorite MFA app to `/auth/mfa/totp`:
```shell
curl -d '{"ticket":"<generated-ticket>", code":"<verification-code>"}' -H "Content-Type: application/json" -X POST http://localhost:3000/auth/mfa/totp`
```
The HBP session is then opened with the client, and the JWT is sent back as the payload:
```json
{
"jwt_token": "<the user Hasura-compatible JWT>",
"jwt_expires_in": "<the number of milliseconds of validity of the JWT>"
}
```
### Disable
## JWT
@@ -93,6 +161,29 @@ You can however add some safeguards and limitations to the registration process
- How to get the JWT
-> link to cookie specs in the configuration page -->
When the user logs in, HBP sets an HTTP-Only cookie to store session information and a refresh token.
::: warning
Never store a JWT in the local storage of the browser as it is prone to XSS attacks! Keep a short expiration period instead, and get a refreshed JWT through HBP.
:::
The `jwt_expires_in` indicates the maximum frequency in which the browser will need to refresh the JWT.
You can get a refreshed JWT throught the `/auth/token/refresh` GET endpoint:
```shell
curl -H "Content-Type: application/json" http://localhost:3000/auth/token/refresh`
```
It will return the same kind of payload as in `/auth/login`, with a new JWT:
```json
{
"jwt_token": "<the user Hasura-compatible JWT>",
"jwt_expires_in": "<the number of milliseconds of validity of the JWT>"
}
```
## Enable an OAuth provider
## Change email

View File

@@ -2,4 +2,4 @@ import { Router } from 'express'
import refreshToken from './refresh'
import revokeToken from './revoke'
export default Router().post('/refresh', refreshToken).post('/revoke', revokeToken)
export default Router().get('/refresh', refreshToken).post('/revoke', revokeToken)

View File

@@ -3,7 +3,7 @@ import 'jest-extended'
import { request } from '@test/test-mock-account'
it('should refresh the token', async () => {
const { body, status } = await request.post('/auth/token/refresh')
const { body, status } = await request.get('/auth/token/refresh')
expect(status).toEqual(200)