Why Use ASAP (Atlassian) Auth for REST APIs | How To Test It? 🦉
As a senior developer who works extensively with APIs, security and efficiency are always top priorities. When it comes to securing REST APIs, there are numerous authentication methods available, but not all are created equal.
Atlassian's ASAP (Authentication for Services and Projects) Auth stands out as a robust, scalable, and secure option, particularly when dealing with microservices or APIs that require strong authentication mechanisms. But before diving into why ASAP is such a great choice, let’s take a quick look at what REST APIs are and why they matter.
What are REST APIs? đź’»
REST (Representational State Transfer) APIs are a set of rules that allow for the creation of web services that are lightweight, maintainable, and scalable. They follow a stateless, client-server architecture where the server processes the client's request and sends back a response, usually in JSON or XML format. REST APIsare widely used because of their simplicity, scalability, and ability to separate the user interface from the server, which makes them ideal for building web services that can be accessed by various clients, including web browsers, mobile devices, and other servers.
What is ASAP Auth? 🛡️
ASAP (Authentication for Services and Projects) is a token-based authentication mechanism developed by Atlassian. It’s designed specifically for service-to-service communication, where one service needs to securely call another. Instead of relying on user credentials or OAuth (which is more user-centric), ASAP uses JWT (JSON Web Tokens) to grant temporary access to services. This is particularly useful in microservice architectures, where services need to authenticate and authorize requests efficiently without the overhead of managing user sessions or credentials.
Key Features of ASAP Auth:
JWT-Based: ASAP relies on JWT tokens, which are compact, URL-safe, and can carry claims that represent the identity and permissions of the requester.
Stateless: The server doesn’t need to store any session information, as all the necessary information is encoded in the JWT.
Secure: ASAP tokens are signed using a private key, ensuring that only authorized services can generate valid tokens.
Scalable: Ideal for microservice architectures, where services communicate frequently with each other.
How to Implement ASAP Auth in Python, Java, and Go 🔍
Now that we understand the basics of ASAP Auth, let’s look at how you can implement it in various programming languages.
Python Implementation
import jwt
import requests
from datetime import datetime, timedelta
import os
# Define ASAP token creation function
def create_asap_token(issuer, audience, private_key):
current_time = datetime.utcnow()
payload = {
'iss': issuer,
'aud': audience,
'iat': current_time,
'exp': current_time + timedelta(minutes=5),
}
token = jwt.encode(payload, private_key, algorithm='RS256')
return token
# Load private key from environment variable or file
private_key = os.getenv('PRIVATE_KEY')
if not private_key:
with open('path_to_private_key.pem', 'r') as key_file:
private_key = key_file.read()
issuer = 'your-service'
audience = 'target-service'
token = create_asap_token(issuer, audience, private_key)
if isinstance(token, bytes):
token = token.decode('utf-8')
headers = {
'Authorization': f'Bearer {token}'
}
try:
response = requests.get('https://api.target-service.com/data', headers=headers)
response.raise_for_status() # Raises HTTPError for bad responses
print(response.json())
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
Java Implementation
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.util.Date;
public class ASAPAuthExample {
public static PrivateKey loadPrivateKey(String filename) throws Exception {
String key = new String(Files.readAllBytes(Paths.get(filename)))
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s", "");
byte[] keyBytes = java.util.Base64.getDecoder().decode(key);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
public static String createASAPToken(String issuer, String audience, PrivateKey privateKey) {
Algorithm algorithm = Algorithm.RSA256(null, privateKey);
Instant now = Instant.now();
return JWT.create()
.withIssuer(issuer)
.withAudience(audience)
.withIssuedAt(Date.from(now))
.withExpiresAt(Date.from(now.plusSeconds(300))) // 5 minutes expiry
.sign(algorithm);
}
public static void main(String[] args) {
try {
String issuer = "your-service";
String audience = "target-service";
PrivateKey privateKey = loadPrivateKey("path_to_private_key.pem");
String token = createASAPToken(issuer, audience, privateKey);
// Use the token to make a secure API request (using your preferred HTTP client)
System.out.println("Generated Token: " + token);
} catch (Exception e) {
System.err.println("Error creating token: " + e.getMessage());
}
}
}
Go Implementation
package main
import (
"fmt"
"io/ioutil"
"time"
"github.com/golang-jwt/jwt"
)
func loadPrivateKey(path string) (*rsa.PrivateKey, error) {
keyData, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
return jwt.ParseRSAPrivateKeyFromPEM(keyData)
}
func createASAPToken(issuer, audience, privateKeyPath string) (string, error) {
privateKey, err := loadPrivateKey(privateKeyPath)
if err != nil {
return "", err
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"iss": issuer,
"aud": audience,
"iat": time.Now().Unix(),
"exp": time.Now().Add(5 * time.Minute).Unix(),
})
tokenString, err := token.SignedString(privateKey)
if err != nil {
return "", err
}
return tokenString, nil
}
func main() {
issuer := "your-service"
audience := "target-service"
privateKeyPath := "path_to_private_key.pem"
token, err := createASAPToken(issuer, audience, privateKeyPath)
if err != nil {
fmt.Println("Error creating token:", err)
return
}
// Use the token to make a secure API request (using your preferred HTTP client)
fmt.Println("Generated Token:", token)
}
How to Test ASAP Auth Using Toolsđź’ˇ
Testing ASAP authentication requires tools that can send HTTP requests with custom headers. Here’s how you can do it using EchoAPI and cURL.
Testing with EchoAPI🦉
Select API Method and URL:
Choose the correct HTTP method (e.g., POST, GET) and enter the API endpoint URL.
Navigate to 'Auth' Tab:
Click on the Auth tab in the request panel.
Choose ASAP (Atlassian) Auth:
From the Type dropdown, select ASAP (Atlassian).
Configure Algorithm and Fields:
Algorithm: Choose the signing algorithm (e.g., HS256).
Issuer: Enter the identity generating the token.
Audience: Provide the intended recipients of the token.
Key ID: Input the identifier for the signing key.
Private Key: Enter the signing key.
Save and Send:
Click Save, then Send to execute the request with ASAP authentication
Testing with cURL
curl -X GET "https://api.target-service.com/data" \
-H "Authorization: Bearer <your-asap-token>"
This command sends the ASAP token as part of the HTTP header, and you can inspect the response directly in the terminal.
Conclusion đź“ť
ASAP Auth provides a robust, scalable, and secure way to handle authentication in service-to-service communications, especially within microservice architectures. By leveraging JWT, ASAP enables stateless, token-based authentication, which is crucial for maintaining high security and performance. Whether you’re working in Python, Java, or Go, implementing ASAP Auth is straightforward and integrates well into existing workflows.
Furthermore, testing this authentication method using tools like EchoAPI or cURL ensures that your implementation is secure and functioning correctly. As you continue to build and secure your REST APIs, consider using ASAP Auth to enhance both security and efficiency across your services.
Try EchoAPI Interceptor today!
Subscribe to my newsletter
Read articles from Issy directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by