.wpb_animate_when_almost_visible { opacity: 1; }

OAuth U2M in a nutshell

Published: July 19, 2024

Before you can use Orange APIs, there are various steps that are needed to get you started on the Orange Developer portal. These steps are described in: How to start with Orange Developer.

The OAuth U2M in a nutshell guide presents the OAuth2 User To Machine authentication process in a simplified way. It dynamically provides various sample codes. The stepper below shows the various steps, which are clickable:

Before starting

  • Register your client application on the Orange Developer portal to obtain your `client_id` and `client_secret`.
  • You will also need the Fully Qualified Domain Name (FQDN) of the Orange API you wish to access. In this guide we will use `api.orange.com` as an example.
  • Keep your `client_id` and `client_secret` secure as they are used to identify your application and enable API calls

Below is a diagram of the various steps for the OAuth2 authentication:

3-legged OAuth2 Process

Step 1 - request the authorization code

1. Construct an authorization code request URL with the following mandatory parameters:

  • `response_type=code`
  • `client_id` (provided by Orange)
  • `scope` (the list of API scopes your application requires; individual scopes should be separated by whitespace, and the whole line URL-encoded)
  • `redirect_uri` (the URL on which your application wishes to receive the authorization code; this URL must be registered beforehand under the config section of your application on Orange Developer portal)
  • `state` (an opaque value used by the client to maintain state between the authorization code request and the callback. The authorization server includes this value when redirecting the user-agent back to the client. This parameter SHOULD be used for preventing cross-site request forgery)

Example URL:

https://api.orange.com/openidconnect/fr/v1/authorize?response_type=code&client_id=YOUR_CLIENT_ID&scope=SCOPE&redirect_uri=YOUR_REDIRECT_URI&state=YOUR_STATE

2. Direct the resource owner (the end-user) to this constructed URI using HTTP redirection responses, or by other means available to it via the user-agent. This way, the resource owner will be in direct contact with the authorization server and will be able to grant the access request.

Step 2 - request the OAuth access token by exchanging it against the authorization code

1. Assuming the resource owner grants access, the authorization server redirects the user-agent back to your redirection URI provided earlier. The redirection URI includes an authorization code and any local state you provided earlier.

2. Send a POST request to the token endpoint with the following parameters:

  • `authorization_header` (your application credentials encoded in base64)
  • `grant_type=authorization_code`
  • `code` (the authorization code received)
  • `redirect_uri` (must be the same as the one used in the authorization request)
Example cURL request:
curl -X POST \
-H "Authorization: Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET" \
-d "grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI" \
https://api.orange.com/openidconnect/fr/v1/token

Example cURL

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.orange.com/openidconnect/fr/v1/token');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
   'Authorization: Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET',
   'Content-Type: application/x-www-form-urlencoded',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI');

$response = curl_exec($ch);

curl_close($ch);
using System.Net.Http;

using System.Net.Http.Headers;

 HttpClient client = new HttpClient();

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://api.orange.com/openidconnect/fr/v1/token");

request.Headers.Add("Authorization", "Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET");

request.Content = new StringContent("grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
import java.io.IOException
import okhttp3.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request

val client = OkHttpClient()

val formBody = FormBody.Builder()
  .add("grant_type", "authorization_code")
  .add("code", "AUTHORIZATION_CODE")
  .add("redirect_uri", "YOUR_REDIRECT_URI")
  .build()

val request = Request.Builder()
  .url("https://api.orange.com/openidconnect/fr/v1/token")
  .post(formBody)
  .header("Authorization", "Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET")
  .header("Content-Type", "application/x-www-form-urlencoded")
  .build()

client.newCall(request).execute().use { response ->
  if (!response.isSuccessful) throw IOException("Unexpected code $response")
  response.body!!.string()
}
extern crate reqwest;
use reqwest::header;

fn main() -> Result<(), Box<dyn std::error::Error>> {
  let mut headers = header::HeaderMap::new();
  headers.insert("Authorization", "Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET".parse().unwrap());
  headers.insert("Content-Type", "application/x-www-form-urlencoded".parse().unwrap());

  let client = reqwest::blocking::Client::builder()
     .redirect(reqwest::redirect::Policy::none())
     .build()
     .unwrap();
  let res = client.post("https://api.orange.com/openidconnect/fr/v1/token")
     .headers(headers)
     .body("grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI")
     .send()?
     .text()?;
  println!("{}", res);

  Ok(())
}

Example fetch

fetch('https://api.orange.com/openidconnect/fr/v1/token', {
  method: 'POST',
  headers: { 
    'Authorization': 'Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET'
  },
  body: new URLSearchParams({
    'grant_type': 'authorization_code',
    'code': 'AUTHORIZATION_CODE',
    'redirect_uri': 'YOUR_REDIRECT_URI'
  })
});

Example jQuery

$.ajax({
  url: 'https://api.orange.com/openidconnect/fr/v1/token',
  crossDomain: true,
  method: 'post',
  headers: {
     'Authorization': 'Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET'
  },
  contentType: 'application/x-www-form-urlencoded',
  data: {
     'grant_type': 'authorization_code',
     'code': 'AUTHORIZATION_CODE',
     'redirect_uri': 'YOUR_REDIRECT_URI'
  }
}).done(function(response) {
  console.log(response);
});

Example XHR

const data = new URLSearchParams({
    'grant_type': 'authorization_code',
    'code': 'AUTHORIZATION_CODE',
    'redirect_uri': 'YOUR_REDIRECT_URI'
});
let xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('POST', 'https://api.orange.com/openidconnect/fr/v1/token');
xhr.setRequestHeader('Authorization', 'Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

xhr.onload = function() {
  console.log(xhr.response);
};

xhr.send(data);

Example HttpClient

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://api.orange.com/openidconnect/fr/v1/token"))
  .POST(BodyPublishers.ofString("grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI"))
  .setHeader("Authorization", "Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET")
  .setHeader("Content-Type", "application/x-www-form-urlencoded")
  .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

Example HttpURLConnection

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

class Main {
  public static void main(String[] args) throws IOException {
     URL url = new URL("https://api.orange.com/openidconnect/fr/v1/token");
     HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
     httpConn.setRequestMethod("POST");

     httpConn.setRequestProperty("Authorization", "Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET");
     httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

     httpConn.setDoOutput(true);
     OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
     writer.write("grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI");
     writer.flush();
     writer.close();
     httpConn.getOutputStream().close();

     InputStream responseStream = httpConn.getResponseCode() / 100 == 2
        ? httpConn.getInputStream()
        : httpConn.getErrorStream();
     Scanner s = new Scanner(responseStream).useDelimiter("\A");
     String response = s.hasNext() ? s.next() : "";
     System.out.println(response);
  }
}

Example jsop

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.jsoup.Connection;
import org.jsoup.Jsoup;

class Main {

    public static void main(String[] args) throws IOException {
           Connection.Response response = Jsoup.connect("https://api.orange.com/openidconnect/fr/v1/token")
                 .header("Authorization", "Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET")
                 .header("Content-Type", "application/x-www-form-urlencoded")
                 .requestBody("grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI")
                 .method(org.jsoup.Connection.Method.POST)
                 .ignoreContentType(true)
                 .execute();

           System.out.println(response.parse());
      }
}

Example okHttp

import java.io.IOException;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

OkHttpClient client = new OkHttpClient();

RequestBody formBody = new FormBody.Builder()
  .add("grant_type", "authorization_code")
  .add("code", "AUTHORIZATION_CODE")
  .add("redirect_uri", "YOUR_REDIRECT_URI")
  .build();

Request request = new Request.Builder()
  .url("https://api.orange.com/openidconnect/fr/v1/token")
  .post(formBody)
  .header("Authorization", "Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET")
  .header("Content-Type", "application/x-www-form-urlencoded")
  .build();

try (Response response = client.newCall(request).execute()) {
  if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  response.body().string();
}

Example node-fetch

import fetch from 'node-fetch';
fetch('https://api.orange.com/openidconnect/fr/v1/token', {
  method: 'POST',
  headers: {
     'Authorization': 'Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET',
  },
  body: new URLSearchParams({
     'grant_type': 'authorization_code'
     'code': 'AUTHORIZATION_CODE',
     'redirect_uri': 'YOUR_REDIRECT_URI'
  })
});

Example http

import https from 'https';
const options = {
  hostname: 'api.orange.com',
  path: '/openidconnect/fr/v1/token',
  method: 'POST',
  headers: {
     'Authorization': 'Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET',
     'Content-Type': 'application/x-www-form-urlencoded',
  }
};

const req = https.request(options, function (res) {
  const chunks = [];

  res.on('data', function (chunk) {
     chunks.push(chunk);
  });

  res.on('end', function () {
     const body = Buffer.concat(chunks);
     console.log(body.toString());
  });
});

req.write(new URLSearchParams({
  'grant_type': 'authorization_code',
  'code': 'AUTHORIZATION_CODE',
  'redirect_uri': 'YOUR_REDIRECT_URI' 
}).toString());
req.end();

Example requests

import requests

headers = {
  'Authorization': 'BASE64_ENCODED_CLIENT_ID_AND_SECRET',
  'Content-Type': 'application/x-www-form-urlencoded',
}

data = {
   'grant_type': 'authorization_code',
   'code': 'AUTHORIZATION_CODE',
   'redirect_uri': 'YOUR_REDIRECT_URI',
}

response = requests.post('https://api.orange.com/openidconnect/fr/v1/token', headers=headers, data=data)

Example http.client

import http.client

conn = http.client.HTTPSConnection('api.orange.com')
headers = {
  'Authorization': 'Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET',
  'Content-Type': 'application/x-www-form-urlencoded',
}
conn.request(
   'POST',
   '/openidconnect/fr/v1/token',
   'grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=YOUR_REDIRECT_URI',
   headers
)
response = conn.getresponse()

3. On success, you will receive a response with an `access_token` to use for accessing protected resources.

Example response:
json
{
"token_type": "Bearer",
"access_token": "YOUR_NEW_ACCESS_TOKEN",
"expires_in": 3600,
"refresh_token": "YOUR_NEW_REFRESH_TOKEN"
}

Step 3: refresh the OAuth access token (if necessary)

If you have a `refresh_token`, you can use it to obtain a new `access_token` by sending a POST request to the token endpoint with the following parameters:

  • `authorization_header` (your application credentials encoded in base64)
  • `grant_type=refresh_token`
  • `refresh_token` (the refresh token obtained earlier)
Example cURL request:
curl -X POST \
-H "Authorization: Basic BASE64_ENCODED_CLIENT_ID_AND_SECRET" \
-d "grant_type=refresh_token&refresh_token=YOUR_REFRESH_TOKEN" \
https://api.orange.com/openidconnect/fr/v1/token
Example response:
json
{
"token_type": "Bearer",
"access_token": "YOUR_REFRESHED_ACCESS_TOKEN",
"expires_in": 3600,
}

Step 4: access protected resources using the OAuth access token

For each API call to protected resources, include the `access_token` in the HTTP Authorization header as follows: `Authorization: Bearer {access_token}`.

Example cURL request:
curl -X GET \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
https://api.orange.com/{api}/vM/{resource}
Example response:
json
{
"data": "PROTECTED_RESOURCE_DATA"
}

Your application is now ready to consume the Orange API’s resources protected by the 3-legged OAuth protocol.

Learn more

provides you with a step-by-step guide with screen shots to help you get started on Orange Developer

provides you with a complete of possible errors on Orange Developer and how to troubleshoot them

tool that automatically generates code in various languages