curl -X POST "http://localhost:8080/token?grant_type=password" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123"
}'
const response = await fetch('http://localhost:8080/token?grant_type=password', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'user@example.com',
password: 'securepassword123'
}),
});
const authData = await response.json();
import requests
data = {
"email": "user@example.com",
"password": "securepassword123"
}
response = requests.post(
'http://localhost:8080/token?grant_type=password',
json=data
)
auth_data = response.json()
package main
import (
"bytes"
"encoding/json"
"net/http"
)
func main() {
data := map[string]string{
"email": "user@example.com",
"password": "securepassword123",
}
jsonData, _ := json.Marshal(data)
resp, err := http.Post(
"http://localhost:8080/token?grant_type=password",
"application/json",
bytes.NewBuffer(jsonData),
)
// Handle response...
}
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjQwOTk1MjAwLCJpYXQiOjE2NDA5MDg4MDAsImlzcyI6Imh0dHBzOi8veW91ci1wcm9qZWN0LnN1cGFiYXNlLmNvL2F1dGgvdjEiLCJzdWIiOiIxMjNlNDU2Ny1lODliLTEyZDMtYTQ1Ni00MjY2MTQxNzQwMDAiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9...",
"token_type": "bearer",
"expires_in": 3600,
"expires_at": 1640995200,
"refresh_token": "refresh_token_string_here",
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"aud": "authenticated",
"role": "authenticated",
"email": "user@example.com",
"phone": null,
"email_confirmed_at": "2023-01-01T00:00:00Z",
"phone_confirmed_at": null,
"last_sign_in_at": "2023-01-01T12:00:00Z",
"app_metadata": {
"provider": "email",
"providers": ["email"]
},
"user_metadata": {
"first_name": "John",
"last_name": "Doe"
},
"created_at": "2023-01-01T00:00:00Z",
"updated_at": "2023-01-01T12:00:00Z"
}
}
Authentication
User Login
Login and token refresh using OAuth2 token endpoint
POST
/
token
curl -X POST "http://localhost:8080/token?grant_type=password" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123"
}'
const response = await fetch('http://localhost:8080/token?grant_type=password', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'user@example.com',
password: 'securepassword123'
}),
});
const authData = await response.json();
import requests
data = {
"email": "user@example.com",
"password": "securepassword123"
}
response = requests.post(
'http://localhost:8080/token?grant_type=password',
json=data
)
auth_data = response.json()
package main
import (
"bytes"
"encoding/json"
"net/http"
)
func main() {
data := map[string]string{
"email": "user@example.com",
"password": "securepassword123",
}
jsonData, _ := json.Marshal(data)
resp, err := http.Post(
"http://localhost:8080/token?grant_type=password",
"application/json",
bytes.NewBuffer(jsonData),
)
// Handle response...
}
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjQwOTk1MjAwLCJpYXQiOjE2NDA5MDg4MDAsImlzcyI6Imh0dHBzOi8veW91ci1wcm9qZWN0LnN1cGFiYXNlLmNvL2F1dGgvdjEiLCJzdWIiOiIxMjNlNDU2Ny1lODliLTEyZDMtYTQ1Ni00MjY2MTQxNzQwMDAiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9...",
"token_type": "bearer",
"expires_in": 3600,
"expires_at": 1640995200,
"refresh_token": "refresh_token_string_here",
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"aud": "authenticated",
"role": "authenticated",
"email": "user@example.com",
"phone": null,
"email_confirmed_at": "2023-01-01T00:00:00Z",
"phone_confirmed_at": null,
"last_sign_in_at": "2023-01-01T12:00:00Z",
"app_metadata": {
"provider": "email",
"providers": ["email"]
},
"user_metadata": {
"first_name": "John",
"last_name": "Doe"
},
"created_at": "2023-01-01T00:00:00Z",
"updated_at": "2023-01-01T12:00:00Z"
}
}
OAuth2 token endpoint supporting password grant (login) and refresh token grant. This endpoint authenticates users and returns access tokens for API access.
Example authenticated request:
Password Grant (Login)
Authenticate a user with email/phone and password to receive access and refresh tokens.curl -X POST "http://localhost:8080/token?grant_type=password" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123"
}'
const response = await fetch('http://localhost:8080/token?grant_type=password', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'user@example.com',
password: 'securepassword123'
}),
});
const authData = await response.json();
import requests
data = {
"email": "user@example.com",
"password": "securepassword123"
}
response = requests.post(
'http://localhost:8080/token?grant_type=password',
json=data
)
auth_data = response.json()
package main
import (
"bytes"
"encoding/json"
"net/http"
)
func main() {
data := map[string]string{
"email": "user@example.com",
"password": "securepassword123",
}
jsonData, _ := json.Marshal(data)
resp, err := http.Post(
"http://localhost:8080/token?grant_type=password",
"application/json",
bytes.NewBuffer(jsonData),
)
// Handle response...
}
Query Parameters
string
required
The OAuth2 grant type. Use
password for login or refresh_token for token refresh.Request Body (Password Grant)
string
User’s email address. Either email or phone is required.
string
User’s phone number in international format. Either email or phone is required.
string
required
User’s password.
Refresh Token Grant
Use a refresh token to obtain new access tokens without re-authentication.curl -X POST "http://localhost:8080/token?grant_type=refresh_token" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "your_refresh_token_here"
}'
const response = await fetch('http://localhost:8080/token?grant_type=refresh_token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
refresh_token: 'your_refresh_token_here'
}),
});
const authData = await response.json();
Request Body (Refresh Token Grant)
string
required
The refresh token obtained from a previous authentication.
Response
string
JWT access token for authenticating API requests
string
Token type, always “bearer”
integer
Token expiration time in seconds (typically 3600 for 1 hour)
integer
Token expiration timestamp (Unix timestamp)
string
Refresh token for obtaining new access tokens
object
User information object
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjQwOTk1MjAwLCJpYXQiOjE2NDA5MDg4MDAsImlzcyI6Imh0dHBzOi8veW91ci1wcm9qZWN0LnN1cGFiYXNlLmNvL2F1dGgvdjEiLCJzdWIiOiIxMjNlNDU2Ny1lODliLTEyZDMtYTQ1Ni00MjY2MTQxNzQwMDAiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9...",
"token_type": "bearer",
"expires_in": 3600,
"expires_at": 1640995200,
"refresh_token": "refresh_token_string_here",
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"aud": "authenticated",
"role": "authenticated",
"email": "user@example.com",
"phone": null,
"email_confirmed_at": "2023-01-01T00:00:00Z",
"phone_confirmed_at": null,
"last_sign_in_at": "2023-01-01T12:00:00Z",
"app_metadata": {
"provider": "email",
"providers": ["email"]
},
"user_metadata": {
"first_name": "John",
"last_name": "Doe"
},
"created_at": "2023-01-01T00:00:00Z",
"updated_at": "2023-01-01T12:00:00Z"
}
}
Error Responses
{
"code": 400,
"msg": "Invalid credentials",
"details": "Email or password is incorrect"
}
{
"code": 400,
"msg": "Invalid refresh token",
"details": "Refresh token is expired or invalid"
}
{
"code": 422,
"msg": "Email not confirmed",
"details": "Please confirm your email before signing in"
}
{
"code": 429,
"msg": "Too many requests",
"details": "Rate limit exceeded. Try again later."
}
Using Access Tokens
Include the access token in the Authorization header for authenticated requests:Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
curl -X GET "http://localhost:8080/user" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json"
Token Refresh Strategy
Implement automatic token refresh in your application:class AuthClient {
constructor() {
this.accessToken = null;
this.refreshToken = null;
}
async refreshAccessToken() {
const response = await fetch('/token?grant_type=refresh_token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refresh_token: this.refreshToken })
});
const data = await response.json();
this.accessToken = data.access_token;
this.refreshToken = data.refresh_token;
}
async makeRequest(url, options = {}) {
// Add auth header
const headers = {
'Authorization': `Bearer ${this.accessToken}`,
...options.headers
};
let response = await fetch(url, { ...options, headers });
// If token expired, refresh and retry
if (response.status === 401) {
await this.refreshAccessToken();
headers['Authorization'] = `Bearer ${this.accessToken}`;
response = await fetch(url, { ...options, headers });
}
return response;
}
}
Phone Number Login
To login with a phone number instead of email:{
"phone": "+1234567890",
"password": "securepassword123"
}
Rate Limiting
This endpoint is rate limited to prevent brute force attacks:- Password Grant: 5 attempts per minute per IP address
- Refresh Token Grant: 10 requests per minute per user
Security Features
- Secure Password Hashing: Passwords are verified using bcrypt
- Token Rotation: Refresh tokens are rotated on each use
- Rate Limiting: Protection against brute force attacks
- Audit Logging: All authentication attempts are logged
Next Steps
After successful authentication:- Store tokens securely - Save access and refresh tokens
- Make authenticated requests - Use the access token in API calls
- Handle token expiration - Implement automatic refresh logic
- Implement logout - Use the logout endpoint