Python · API · Intermediate

JWT Authentication

5 tasks

Use JSON Web Tokens for authentication, understand access/refresh token flow, and handle token refresh.

JWT — access and refresh tokens

#
JWT (JSON Web Token) is a second authentication scheme offered by the API alongside Token auth. The key difference: instead of one token, you get two. - Access token — short-lived (minutes or hours). You send this on every request. - Refresh token — long-lived (days). You only use it to get a new access token when the old one expires. Why two tokens? If an access token is stolen, it can only be misused for a short time. The refresh token stays safe because it travels less frequently — only when renewing access. The authorization header format for JWT uses 'Bearer' instead of 'Token': ``` Authorization: Bearer <access_token> ``` In requests: ```python import requests BASE_URL = 'https://apilearn.tukas.dev' access_token = '...' headers = {'Authorization': f'Bearer {access_token}'} response = requests.get(f'{BASE_URL}/api/users/profile/', headers=headers) ``` When the access token expires, you do not need to ask the user for credentials again. Send the refresh token to the refresh endpoint and you get a fresh access token back: ```python response = requests.post( f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh_token}, ) new_access = response.json()['access'] ``` Token auth vs JWT — when to prefer which: - Token auth is simpler: one token, straightforward header, no expiry to manage. - JWT is more secure for long-lived sessions: access tokens expire quickly, reducing risk if intercepted. Standard in modern mobile apps and SPAs. For scripts and short-lived automation, Token auth is often enough. JWT becomes important when you are building something that stays authenticated over days or weeks.

Getting and refreshing JWT tokens

#
Get a JWT pair (you need a registered user — see the token-auth topic): ```python import requests BASE_URL = 'https://apilearn.tukas.dev' credentials = {'username': 'alice42', 'password': 'securepass123'} response = requests.post(f'{BASE_URL}/api/auth/jwt/', json=credentials) tokens = response.json() access = tokens['access'] refresh = tokens['refresh'] print('access:', access[:20], '...') print('refresh:', refresh[:20], '...') ``` Use the access token to call a protected endpoint: ```python headers = {'Authorization': f'Bearer {access}'} profile = requests.get(f'{BASE_URL}/api/users/profile/', headers=headers).json() print(profile['username']) # 'alice42' ``` When the access token expires, use the refresh token to get a new one: ```python response = requests.post( f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh}, ) new_access = response.json()['access'] print('new access token obtained') # Use the new access token for the next request headers = {'Authorization': f'Bearer {new_access}'} ``` A practical pattern — wrap the auth flow in functions: ```python def get_tokens(username, password): response = requests.post( f'{BASE_URL}/api/auth/jwt/', json={'username': username, 'password': password}, ) return response.json()['access'], response.json()['refresh'] def refresh_access(refresh_token): response = requests.post( f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh_token}, ) return response.json()['access'] access, refresh = get_tokens('alice42', 'securepass123') headers = {'Authorization': f'Bearer {access}'} # ... later, if access expires: access = refresh_access(refresh) ```

JWT reference

#
JWT endpoints: ``` POST /api/auth/jwt/ Get access + refresh token pair body: {username, password} returns: {access: '...', refresh: '...'} POST /api/auth/jwt/refresh/ Refresh access token body: {refresh: '...'} returns: {access: '...', refresh: '...'} ``` Authorization header: ``` Authorization: Bearer <access_token> ``` Token auth vs JWT: ``` Token auth JWT Header Token <t> Bearer <t> Token count 1 2 (access + refresh) Expiry None by default Access expires, refresh is long-lived Refresh flow Not needed POST /api/auth/jwt/refresh/ Best for Scripts, simple Long sessions, mobile, SPAs ``` Example: ```python # Get tokens r = requests.post(f'{BASE_URL}/api/auth/jwt/', json={'username': u, 'password': p}) access, refresh = r.json()['access'], r.json()['refresh'] # Use headers = {'Authorization': f'Bearer {access}'} # Refresh r = requests.post(f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh}) access = r.json()['access'] ```
01

Get a JWT token pair

#

POST to /api/auth/jwt/ with your username and password. Print the first 30 characters of both the access and refresh tokens.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

credentials = {'username': 'YOUR_USERNAME', 'password': 'YOUR_PASSWORD'}

# Get JWT pair and print the first 30 chars of each token
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

credentials = {'username': 'YOUR_USERNAME', 'password': 'YOUR_PASSWORD'}
response = requests.post(f'{BASE_URL}/api/auth/jwt/', json=credentials)
tokens = response.json()
print(tokens['access'][:30])
print(tokens['refresh'][:30])
02

Use Bearer auth

#

Get a JWT access token and use it with the Bearer scheme to GET /api/users/profile/. Print the username and email from the response.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

# Get access token, then GET profile with Authorization: Bearer <token>
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

r = requests.post(f'{BASE_URL}/api/auth/jwt/', json={
    'username': 'YOUR_USERNAME', 'password': 'YOUR_PASSWORD',
})
access = r.json()['access']

headers = {'Authorization': f'Bearer {access}'}
profile = requests.get(f'{BASE_URL}/api/users/profile/', headers=headers).json()
print(profile['username'])
print(profile['email'])
03

Refresh an access token

#

Get a JWT pair, then immediately use the refresh token to get a new access token via POST /api/auth/jwt/refresh/. Print the new access token (first 30 characters).

import requests

BASE_URL = 'https://apilearn.tukas.dev'

# 1. Get initial token pair
# 2. Use refresh token to get a new access token
# 3. Print the first 30 chars of the new access token
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

r = requests.post(f'{BASE_URL}/api/auth/jwt/', json={
    'username': 'YOUR_USERNAME', 'password': 'YOUR_PASSWORD',
})
refresh = r.json()['refresh']

r2 = requests.post(f'{BASE_URL}/api/auth/jwt/refresh/', json={'refresh': refresh})
new_access = r2.json()['access']
print(new_access[:30])
04

Write get_access_token()

#

Write a function get_access_token(username, password) that returns a fresh JWT access token. Call it and print the result.

import requests

BASE_URL = 'https://apilearn.tukas.dev'

def get_access_token(username, password):
    # POST to /api/auth/jwt/ and return the access token
    pass

token = get_access_token('YOUR_USERNAME', 'YOUR_PASSWORD')
print(token[:30])
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

def get_access_token(username, password):
    response = requests.post(
        f'{BASE_URL}/api/auth/jwt/',
        json={'username': username, 'password': password},
    )
    return response.json()['access']

token = get_access_token('YOUR_USERNAME', 'YOUR_PASSWORD')
print(token[:30])
05

Write refresh_access()

#

Write a function refresh_access(refresh_token) that returns a new access token using the refresh endpoint. Then write a small script that gets the initial pair and immediately refreshes the access token, printing both the original and new access tokens (first 20 characters each).

import requests

BASE_URL = 'https://apilearn.tukas.dev'

def refresh_access(refresh_token):
    # POST to /api/auth/jwt/refresh/ and return the new access token
    pass

# Get initial pair, then refresh
Solution
import requests

BASE_URL = 'https://apilearn.tukas.dev'

def refresh_access(refresh_token):
    response = requests.post(
        f'{BASE_URL}/api/auth/jwt/refresh/',
        json={'refresh': refresh_token},
    )
    return response.json()['access']

r = requests.post(f'{BASE_URL}/api/auth/jwt/', json={
    'username': 'YOUR_USERNAME', 'password': 'YOUR_PASSWORD',
})
original_access = r.json()['access']
refresh_token = r.json()['refresh']

new_access = refresh_access(refresh_token)

print('original:', original_access[:20])
print('refreshed:', new_access[:20])