Skip to content

Commit

Permalink
Update auth docs to include fetch/curl examples for getting, passing …
Browse files Browse the repository at this point in the history
…and refreshing tokens
  • Loading branch information
campb303 committed Mar 24, 2021
1 parent b3efaf4 commit 1a20353
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 2 deletions.
128 changes: 126 additions & 2 deletions docs/api/Authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

The webqueue2 API uses a two stage authentication system combining Active Directory and [HTTP Token](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) (or "bearer") authentication.

## Getting an Access Token
All API calls require an access token. You can get an access token by making a POST request to the `/api/login` endpoint containing the JSON encoded username and password of a valid user.

??? info "Who is a valid user?"
Expand Down Expand Up @@ -52,6 +53,8 @@ All API calls require an access token. You can get an access token by making a P
header = "Content-Type: application/json"
data = {"username":"USERNAME","password":"PASSWORD"}
url = "{{ production_url }}/api/login"
# Save cookies for future API calls
cookies = "wq_cookies"
```

Restrict read permissions to your user:
Expand All @@ -65,12 +68,133 @@ All API calls require an access token. You can get an access token by making a P
```
```
# Expected Output:
{"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTYxODI1MjMsIm5iZiI6MTYxNjE4MjUyMywianRpIjoiYzI2ZjY4NDctZGU2OC00ODUzLWI4ODctMTBmZDAyMDcyY2U0IiwiZXhwIjoxNjE2MTgzNDIzLCJzdWIiOiJjYW1wYjMwMyIsImZyZXNoIjpmYWxzZSwidHlwZSI6ImFjY2VzcyIsImNzcmYiOiJjYjYzZWE1My1jOWQ2LTQ5YTItYmZhMi0wY2U4N2Q3YzcxZDcifQ.T7bezsOMreMCXWR0R5w5BKI673hpOquCOnvT1XkyDjY"}
{"access_token": "{{ example_access_token }}"}
```

??? tip "Tip for Parsing Tokens in Bash"
You can parse the access token using Python like this:
```bash
curl -K ~/wq_login.config | \
python3 -c "import sys, json; print(json.load(sys.stdin)['access_token'])"
```
```

## Making Calls With Access Token
To interact with the API, add an `Authorization` header to your request with a value of `Bearer TOKEN` where `TOKEN` is your access token.

Example: Get item `ce100`
=== "fetch"
```javascript
const ce100 = (async _ => {
const loginInit = {
method: "GET",
headers: {'Authentication': 'Bearer {{ example_access_token }}'},
};

let apiResponse = await fetch("{{ production_url }}/api/data/ce/100", loginInit);
let data = await apiResponse.json();

if (data === null){
return false;
}

if (!apiResponse.ok){
console.error(`Fetching item ce100 failed. Got code ${apiResponse.status} (${apiResponse.statusText})`);
return false;
}

return data || false;
})();
```

=== "cURL"
Create a cURL config file named `wq_get_ce100.config`:
```bash
nano ~/wq_get_ce100.config
```

Set cURL options
```python
# ~/wq_get_ce100.config
request = GET
header = "Authorization: Bearer {{ example_access_token }}"
url = "{{ production_url }}/api/data/ce/100"
```

Run cURL using your new config file:
```bash
curl -K ~/wq_get_ce100.config
```
```
# Expected Output:
{ 'assignedTo': 'campb303', 'building': '', 'content': [...], 'dateReceived': '2020-06-23T13:25:51-0400', 'department': '', 'headers': [...], 'isLocked': 'ce 100 is locked by knewell using qvi', 'lastUpdated': '2020-12-01T19:53:00-0500', 'number': 100, 'priority': '', 'queue': 'ce', 'status': 'Dont Delete', 'subject': 'Beepboop', 'userAlias': 'campb303', 'userEmail': 'campb303@purdue.edu', 'userName': 'Justin Campbell' }
```

## Refreshing Access Tokens
By default, access tokens expire 15 minutes after being issued and need refreshed. During login, you'll receive two cookies:

Name | Value | Path | Expiration | SameSite
-- | -- | -- | -- | --
`refresh_token_cookie` | Your refresh token. | `/api/tokens/refresh` | 30 Days | Yes
`csrf_refresh_token` | Additional verification data. (e.g. `{{ example_csrf_token }}`) | `/` | Session | Yes

The `refresh_token_cookie` is used to generate a new access token and will be sent back to the server with every request automatically. The `csrf_refresh_token` is used to verify the `refresh_token_cookie` and needs sent back as an `X-CSRF-TOKEN` header.

To refresh your access token, make a POST request to the `/api/tokens/refresh` endpoint with the value of the `csrf_refresh_token` cookies inside a `X-CSRF-TOKEN` header:

=== "fetch"
```javascript
const newAccessToken = (async _ => {
const csrf_refresh_token = some_func_to_get_csrf_token();

const refreshInit = {
method: "POST",
headers: {'X-CSRF-TOKEN': csrf_refresh_token},
};

let refreshResponse = await fetch(`{{ production_url }}/api/tokens/refresh`, refreshInit);
let data = await refreshResponse.json();

if (data === null){
return false;
}
if (!refreshResponse.ok){
console.error(`Refresh failed. Got code ${refreshResponse.status} (${refreshResponse.statusText})`);
return false;
}

return data.access_token || false;
})();
```

=== "cURL"
Create a cURL config file named `wq_refresh.config`:
```bash
nano ~/wq_refresh.config
```

Set cURL options
```python
# ~/wq_refresh.config
request = POST
header = "X-CSRF-TOKEN: {{ example_csrf_token }}"
url = "{{ production_url }}/api/tokens/refresh"
# Pull cookies from login.
cookie-jar = "wq_cookies"
```

Run cURL using your new config file:
```bash
curl -K ~/wq_refresh.config
```
```
# Expected Output:
{"access_token": "{{ example_access_token }}"}
```

??? tip "Tip for Parsing Tokens in Bash"
You can parse the access token using Python like this:
```bash
curl -K ~/wq_login.config | \
python3 -c "import sys, json; print(json.load(sys.stdin)['access_token'])"
```
```
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ extra:
link: https://github.itap.purdue.edu/ECN/webqueue2
name: webqueue2 on GitHub
production_url: "https://engineering.purdue.edu/webqueue/webqueue2/build"
example_access_token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MTY1NTIyMDIsIm5iZiI6MTYxNjU1MjIwMiwianRpIjoiZDgyNGM1MWItM2JmNy00ZDUzLWE0YTgtY2VhZWQ5ZmVjNGYzIiwiZXhwIjoxNjE2NTUzMTAyLCJzdWIiOiJjYW1wYjMwMyIsImZyZXNoIjpmYWxzZSwidHlwZSI6ImFjY2VzcyIsImNzcmYiOiI1Yjk5NWQ5OS05YjIzLTQyMjYtYTc0OC1lMmQ5OTA4MDkzOTQifQ.6z7EReDfhPkBkuAMHEvDuMDV4wVbqrWSjQXdRyv_5hE"
example_csrf_token: "7b7c1ea8-f6bb-4204-99af-cd4124a69d89"

extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/tablesort/5.2.1/tablesort.min.js
Expand Down

0 comments on commit 1a20353

Please sign in to comment.