Skip to main content

OAuth Flow Quickstart

This guide provides a complete walkthrough with working code examples for implementing the OAuth flow. For a conceptual overview of how OAuth works, see Getting Credentials via OAuth.

Prerequisites

Before you begin, ensure you have:

  • Your own integrator service account credentials and an authenticated Noon session for your backend. If you have not set this up yet, start with Getting Your Credentials and Authenticating Your Requests.
  • OAuth client credentials (client_id and client_secret) provided by Noon
  • A redirect URI registered with Noon for receiving authorization codes
  • Basic understanding of OAuth 2.0 authorization code flow
Use your integrator authentication for the OAuth API calls

When your backend calls POST /identity/oauth/v1/token/create and POST /identity/oauth/v1/token/exchange, those requests must be sent with an authenticated Noon session created from your integrator service account credentials.

The OAuth client_id and client_secret identify your application during the code exchange, but they do not make the request authenticated on their own. The seller-scoped credential is returned only after the exchange succeeds.

Implementation Guide

Step 1: Redirect User to Authorization URL

When a seller wants to connect their Noon account to your platform, redirect them to the Noon authorization endpoint:

https://oauth.noon.partners/?client_id=abc123xyz&state=random-state-string-123

Required Query Parameters:

ParameterDescriptionExample
client_idYour OAuth client IDabc123xyz
stateRandom string for CSRF protectionrandom-state-string-123
info

The seller will be presented with a consent screen showing what permissions your application is requesting. They must approve before proceeding.

Step 2: Handle Authorization Callback

After the seller approves, Noon redirects them back to your registered redirect URI with the authorization code:

https://yourapp.com/callback?code=AUTH_CODE_HERE&state=random-state-string-123

Your callback handler must:

  1. Verify the state parameter matches what you sent to prevent CSRF attacks
  2. Extract the authorization code from the code parameter

Example callback handling:

from flask import Flask, request, redirect

app = Flask(__name__)

@app.route('/callback')
def oauth_callback():
# Verify state parameter
state = request.args.get('state')
if state != session.get('oauth_state'): # session refers to any server-side storage you use to track state for that user request
return "Invalid state parameter", 400

# Get authorization code
auth_code = request.args.get('code')
if not auth_code:
return "No authorization code received", 400

# Proceed to exchange code for token
return exchange_code_for_token(auth_code)

Step 3: Exchange Authorization Code for Access Token

Make a server-to-server API call to exchange the authorization code for an access token.

Use the same authenticated integrator session for this request.

Endpoint: POST /identity/oauth/v1/token/create

Request Body:

{
"grant_type": "authorization_code",
"code": "AUTH_CODE_HERE",
"client_id": "your_client_id",
"client_secret": "your_client_secret"
}

Response:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "TOKEN_TYPE_BEARER",
"expires_in": "3600s",
"scopes": ["access:grant"],
"project_code": "PRJ12345"
}
Security Best Practice

Never expose your client_secret in client-side code. This exchange must happen on your backend server.

Important Response Fields:

  • access_token: JWT token needed for the next step (valid for 1 hour and single-use)
  • project_code: The seller's project code to which the service account will have access
  • expires_in: Token validity duration

Step 4: Create Service Account and Receive Credentials

Finally, use the access token to create the service account and receive its credentials.

This request must also reuse your authenticated integrator session.

Endpoint: POST /identity/oauth/v1/token/exchange

Request Body:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response:

{
"status": {
"code": 0
},
"project_code": "PRJ12345",
"oauth_request_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"result": {
"key_id": "key-abc123",
"private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQ...",
"channel_identifier": "[email protected]",
"project_code": "PRJ12345",
"type": "apijwt",
"issued_at": "2026-04-20T12:00:00Z"
}
}

Important Response Fields:

  • status: Indicates whether the workflow executed successfully (code: 0 means success)
  • project_code: The seller's project code
  • oauth_request_id: A unique identifier for tracking this OAuth exchange request — store this to monitor the service account creation progress
  • result: The service account credentials, including the private key needed to authenticate API calls
Store Your Credentials Securely

The result contains the private key, which is only returned once — Noon does not store it. Store it in a secrets manager immediately. If you lose it, you can create a new credential via the API User Service.

Tracking Your Request

Save the oauth_request_id from the response. You can use it to check the status of the request in the OAuth tab of the Noon Partners Access App. This is helpful for debugging or confirming that the workflow completed successfully.

Complete Code Examples

Here are complete, working examples in multiple programming languages:

Authentication required before calling the OAuth API endpoints

These examples assume your backend has already authenticated with Noon using your integrator service account credentials and is reusing that authenticated client or session when calling POST /identity/oauth/v1/token/create and POST /identity/oauth/v1/token/exchange.

The OAuth client_id and client_secret shown in the request body identify your OAuth application, but they do not replace the authenticated integrator session. For the standard login flow, see Authenticating Your Requests.

import json
import uuid
import requests
from flask import Flask, request, session, redirect

app = Flask(__name__)
app.secret_key = 'your-secret-key-here' # Use a secure secret key

# Load your OAuth client credentials
CLIENT_ID = 'your_client_id'
CLIENT_SECRET = 'your_client_secret'

# Step 1: Initiate OAuth flow - redirect user to authorization URL
@app.route('/connect-seller')
def connect_seller():
# Generate and store state for CSRF protection
state = str(uuid.uuid4())
session['oauth_state'] = state

authorization_url = f"https://oauth.noon.partners/?client_id={CLIENT_ID}&state={state}"
return redirect(authorization_url)

# Step 2: Handle callback and verify state
@app.route('/oauth/callback')
def oauth_callback():
# Verify state parameter to prevent CSRF attacks
received_state = request.args.get('state')
stored_state = session.get('oauth_state')

if not received_state or received_state != stored_state:
return "Invalid state parameter - possible CSRF attack", 400

# Clear the stored state
session.pop('oauth_state', None)

# Get authorization code
authorization_code = request.args.get('code')
if not authorization_code:
return "No authorization code received", 400

try:
# Step 3: Exchange authorization code for access token
token_response = get_access_token(authorization_code)
print(f"Access token obtained for project: {token_response['project_code']}")

# Step 4: Exchange access token to create service account and receive credentials
sa_response = create_service_account(token_response['access_token'])
credentials = sa_response['result']
print(f"Credentials received for project: {token_response['project_code']}")
# Store credentials['private_key'] securely — it is only returned once

return f"Successfully connected seller project: {token_response['project_code']}"
except Exception as e:
return f"Error: {e}", 500

# Step 3: Exchange authorization code for access token
def get_access_token(auth_code):
url = 'https://noon-api-gateway.noon.partners/identity/oauth/v1/token/create'
payload = {
'grant_type': 'authorization_code',
'code': auth_code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET
}

response = requests.post(url, json=payload, headers={
'Content-Type': 'application/json',
'User-Agent': 'YourApp/1.0'
})

if response.status_code == 200:
return response.json()
else:
raise Exception(f"Failed to get access token: {response.text}")

# Step 4: Exchange access token to create service account and receive credentials
def create_service_account(access_token):
url = 'https://noon-api-gateway.noon.partners/identity/oauth/v1/token/exchange'
payload = {
'access_token': access_token
}

response = requests.post(url, json=payload, headers={
'Content-Type': 'application/json',
'User-Agent': 'YourApp/1.0'
})

if response.status_code == 200:
return response.json()
else:
raise Exception(f"Failed to create service account: {response.text}")

if __name__ == '__main__':
app.run(debug=True)

Testing Your Integration

Verification Checklist

Before going live with sellers, verify:

  • State parameter is validated to prevent CSRF
  • Authorization codes are used only once
  • Access tokens are stored securely and never logged
  • Token expiry is handled gracefully
  • Client secret is never exposed to clients
  • Error responses are handled appropriately

Security Best Practices

For comprehensive security guidelines, see the Security Considerations in the Getting Credentials via OAuth guide.

1. Protect Your Client Secret

# BAD - Hardcoded secret
client_secret = "my-secret-123"

# GOOD - Use environment variables
import os
client_secret = os.environ.get('NOON_CLIENT_SECRET')

2. Validate State Parameter

# Always validate state
import secrets

# Generate random state
state = secrets.token_urlsafe(32)
session['oauth_state'] = state

# Later, in callback
if request.args.get('state') != session.get('oauth_state'):
raise ValueError("CSRF detected")

3. Use HTTPS Only

# Enforce HTTPS in production
if not request.is_secure and app.env == 'production':
return redirect(request.url.replace('http://', 'https://'))

4. Use Access Tokens Immediately

# Exchange access token immediately after receiving it
# Access tokens are single-use and should be consumed right away
token_response = get_access_token(auth_code)
access_token = token_response['access_token']

# Immediately exchange for service account creation
sa_response = create_service_account(access_token)

Next Steps

Now that you've completed the OAuth flow:

  1. Store the credentials from result securely — Save the private key in a secrets manager and associate it with the seller in your database
  2. Start making API calls — Use the credentials as shown in the Authentication Guide
  3. Rotate or revoke credentials as needed — Use the API User Service to manage credentials over time

Additional Resources

Need Help?

If you encounter issues:

  • Review the error messages in the API response
  • Check the Error Handling section for common issues
  • Contact Support with your client_id (never share client_secret)