JavaScript · API · Intermediate
JWT Authentication
Use JSON Web Tokens for authentication, understand access/refresh token flow, and handle token refresh.
Quick topic start and explanations before exercises (exercises below):
Getting and refreshing JWT tokens
#JWT reference
#Exercises:
Get JWT tokens
#POST to `/api/auth/jwt/` with your credentials. Print both the `access` and `refresh` tokens (first 30 chars of each is enough).
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
// POST /api/auth/jwt/ and print access + refresh (first 30 chars)
}
main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
const response = await fetch(`${BASE_URL}/api/auth/jwt/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
});
const { access, refresh } = await response.json();
console.log('access:', access.slice(0, 30) + '...');
console.log('refresh:', refresh.slice(0, 30) + '...');
}
main();
Use access token for a request
#Get JWT tokens, then use the `access` token with `Bearer` prefix to fetch `/api/users/profile/`. Print `username` and `email`.
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
// get JWT, use access token with Bearer prefix to fetch profile
}
main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
const { access } = await fetch(`${BASE_URL}/api/auth/jwt/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
}).then(r => r.json());
const profile = await fetch(`${BASE_URL}/api/users/profile/`, {
headers: { 'Authorization': `Bearer ${access}` },
}).then(r => r.json());
console.log(profile.username);
console.log(profile.email);
}
main();
Refresh the access token
#Get initial JWT tokens, then immediately call `/api/auth/jwt/refresh/` with the `refresh` token. Print the new `access` token (first 30 chars) and confirm it's different from the old one.
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
// get tokens, then refresh, compare old and new access
}
main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
const { access: oldAccess, refresh } = await fetch(`${BASE_URL}/api/auth/jwt/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
}).then(r => r.json());
const { access: newAccess } = await fetch(`${BASE_URL}/api/auth/jwt/refresh/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refresh }),
}).then(r => r.json());
console.log('Old:', oldAccess.slice(0, 30));
console.log('New:', newAccess.slice(0, 30));
console.log('Different:', oldAccess !== newAccess);
}
main();
Decode the JWT payload
#Get an access token. The JWT payload is the middle part (between the two dots), base64-encoded. Decode it with `atob()` and `JSON.parse()`. Print `user_id` and `exp` from the payload.
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
// get access token
// split by '.', take index 1, decode with atob, parse JSON
// print user_id and exp
}
main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
const { access } = await fetch(`${BASE_URL}/api/auth/jwt/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
}).then(r => r.json());
const payload = JSON.parse(atob(access.split('.')[1]));
console.log('user_id:', payload.user_id);
console.log('exp:', payload.exp);
console.log('expires:', new Date(payload.exp * 1000).toISOString());
}
main();
Full JWT flow
#Write a complete script: get tokens, fetch the profile with `access`, refresh the tokens, then fetch the cart with the new `access`. Print username from the profile and item count from the cart.
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
// 1. get JWT tokens
// 2. fetch profile with access
// 3. refresh tokens
// 4. fetch cart with new access
}
main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';
async function main() {
// 1. Initial tokens
let { access, refresh } = await fetch(`${BASE_URL}/api/auth/jwt/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
}).then(r => r.json());
// 2. Fetch profile
const profile = await fetch(`${BASE_URL}/api/users/profile/`, {
headers: { 'Authorization': `Bearer ${access}` },
}).then(r => r.json());
console.log('Username:', profile.username);
// 3. Refresh
({ access, refresh } = await fetch(`${BASE_URL}/api/auth/jwt/refresh/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refresh }),
}).then(r => r.json()));
// 4. Fetch cart with new token
const cart = await fetch(`${BASE_URL}/api/cart/`, {
headers: { 'Authorization': `Bearer ${access}` },
}).then(r => r.json());
console.log('Cart items:', cart.items.length);
}
main();