Self-Service Machine-to-Machine
If your business case services a non-interactive audience, like APIs or backend servers, you will onboard with a machine-to-machine (M2M) configuration.
Use cases
Use the M2M onboarding path if you:
Support service-to-service communications
Have scheduled jobs or cron tasks running on servers that need to access protected resources or APIs
Allow IoT devices to communicate with backend services or APIs
Have an API layer that needs to communicate with other API layers without user involvement or after a user token has expired
Have a privileged API that may need to be called before a user has authenticated (i.e. from an Action or custom database script in your Auth0 tenant)
Use an API Gateway to manage backend services
Use or support non-interactive applications or other tooling not involving human interaction such as daemons or backend services
How to use this guide
This guide is a pathway to create your M2M implementation in Auth0. We provide considerations, best practices, and concepts you should review.
In Architecture, we advise you to configure Auth0 to support your Software Development Life Cycle and existing infrastructure.
In Create an account, we provide instructions to create your API instance in Auth0 and an application to support the authentication flow (or grant) needed for machine-to-machine authentication.
In Authentication, we walk through the grant you need to use for authentication as well as access tokens and permissions (or scopes) you can set.
In Branding, we advise you where to find information on how to configure Custom Domains depending on how you plan to manage certificates.
In Deployment Automations, you can read about our tooling to assist with deployment.
In Quality Assurance, you can learn more about unit testing, and the readiness checks we provide in Auth0 Dashboard.
Architecture
Before you configure your Auth0 account and tenant, or the groups and structures of your Auth0 services, create a map of your existing infrastructure so you can best leverage Auth0’s capabilities in your existing ecosystem.
As mentioned in common scenarios, you may have other non-interactive technologies in your application domain, network domain, or M2M device domain to consider before you configure Auth0. To review an example M2M scenario, read Server + API. To attempt a hands-on lab working with Node and test API deployment, visit our GitHub repository.
You may want to create a visualization of your current tech stack as well as plan how Auth0 fits in with your current Software Development Lifecycle (SDLC). This can help you determine how many tenants you may need.
Considerations
Before you create a new account or configure your first tenant, you may want to consider:
How you partition or group your APIs to call specific endpoints.
This may determine the audience and other claims on access tokens.
Any third-party consumers to your resource may request an access token for each call. Excessive calls could affect your rate limit.
You can use an API Gateway to limit the number of access tokens a third-party can request. To learn more about API Gateways and Auth0, read Configure an Identity Provider in Access Gateway.
Create an account
Now that you have a plan for your architecture, you’ll configure your Auth0 account and tenants. When you sign up for Auth0 services, you will create your first tenant. This is where you configure Auth0 assets, services, and resources. Sign up to start.
Before you start
In the Auth0 Dashboard or with the Auth0 Management API, create:
An API to represent your API
An M2M application to use the Client Credential Flow
You may want to plan some configuration details before you create an account.
Your tenant name has a role in your Auth0 domain. Before you determine a name, you should review tenant characteristics.
Which Auth0 features you need for your use case. Some features are only available on Professional and Enterprise plans.
Determine if you need to support multiple environments, such as development, staging, and production. To learn more, read Set Up Multiple Environments.
If you have a use case involving thirty-party applications you want to register in a tenant, you can use Dynamic Application Registration based on the OIDC Client Registration specification.
Provision a tenant
Now that you have a plan for your architecture, you’ll configure your Auth0 account and Tenant.
Register an API
In this section, create your API in Auth0.
Start by creating an instance in the Auth0 Dashboard for your APIs.
Follow instructions to register your API.
In the Authentication section, configure your API settings for M2M authentication.
To register an API programmatically, use the Management API. You will need an access token to use Management API. To learn how, read Management API Tokens.
Use the sample provided in Management API Explorer to call the Management API Create a Resource Server endpoint and include the following parameters in the body:
Field | Description | Example |
---|---|---|
Name | A friendly name for the API. Does not affect any functionality. | yourDomain |
Identifier | A unique identifier for the API. Auth0 recommends using a URL. Auth0 does differentiate between URLs that include the last forward slash. For example, https://example.com and https://example.com/ are two different identifiers. The URL does not have to be a publicly available URL. Auth0 will not call your API. This value cannot be modified afterwards. |
https://{yourDomain} |
JSON Web Token (JWT) Profile | The profile determines the format of the access tokens issued for the API. The available values are Auth0 and RFC 9068 . To learn more, read Access Token Profiles. |
access_token |
JSON Web Token (JWT) Signing Algorithm | The algorithm to sign the access tokens with. The available values are HS256 , PS256 , RS256 . If you select RS256 , the token will be signed with the tenant's private key. |
HS256 |
Associate an application
You need to create an association between your application and your API so your application can request access tokens from it. You will learn more about client grants in the Authentication section.
If you create your API in the Dashboard, Auth0 automatically generates a test application and associates it with your API.
Navigate to Auth0 Dashboard > Applications.
Select the test M2M test application created when you created your API.
Switch to the API view, and then locate the API you’d like to enable for this application.
Enable the Authorize toggle, and then select the arrow button on the right to expand the card.
Select Update.
Create an application to associate with your API. Use the sample provided in Management API Explorer to:
Call the Create a Client endpoint. You need to set the
app_type
tonon-interactive
.Call the Create Client Grant endpoint to associate your application to your API.
To learn about application and tenant settings, read Tenant Settings.
Authentication
When calling one API from another API, or from any situation where there is no authenticated user context, you need a way to authorize the application instead of a user. This is a one step process where the application is authenticated (using a client_id
and client_secret
) and then authorized in one call.
For non-interactive applications or services to authentication, you must select a client grant, or authentication flow. The OAuth 2.0 Client Credentials Flow does not require human interaction and is best suited for M2M applications.
Before you start
In Auth0 Dashboard or Management API, you will:
Set your application to use the Client Credentials Flow
Update the scopes for your M2M access tokens
Before you configure your authentication method:
Review the Client Credentials Flow for machine-to-machine authentication. This is the workflow for non-interactive authentication and authorization.
Determine the level of access for your APIs. This helps determine what scopes, or permissions, you will configure when you create your API.
Configure the Client Credential Flow
You can use the Auth0 Dashboard or Management API to set the authentication flow to provide a client credential in exchange for an access token.
Follow the instructions on Update Grant Types to use Auth0 Dashboard or Management API.
M2M access tokens
In token-based authentication, non-interactive clients provide client_id
and client_secret
in a call to the Authentication API token endpoint to get an access token. This access token permits access to your protected API.
The default profile, or format, is the Auth0 token profile associated with two token profiles. You can choose to change the token profile to RFC 9068. To learn more, read Access Token Profiles. To verify the token is valid, your API will check the Signing Algorithms. The default signing algorithm is RSA256, a key-based algorithm.
Example
A request to the /oauth/token
endpoint should be similar to the sample below:
curl --request POST \
--url 'https://{yourDomain}/oauth/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=YOUR_CLIENT_ID \
--data client_secret=YOUR_CLIENT_SECRET \
--data audience=YOUR_API_IDENTIFIER
Was this helpful?
var client = new RestClient("https://{yourDomain}/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Was this helpful?
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://{yourDomain}/oauth/token"
payload := strings.NewReader("grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("content-type", "application/x-www-form-urlencoded")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
Was this helpful?
HttpResponse<String> response = Unirest.post("https://{yourDomain}/oauth/token")
.header("content-type", "application/x-www-form-urlencoded")
.body("grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER")
.asString();
Was this helpful?
var axios = require("axios").default;
var options = {
method: 'POST',
url: 'https://{yourDomain}/oauth/token',
headers: {'content-type': 'application/x-www-form-urlencoded'},
data: new URLSearchParams({
grant_type: 'client_credentials',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
audience: 'YOUR_API_IDENTIFIER'
})
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
Was this helpful?
#import <Foundation/Foundation.h>
NSDictionary *headers = @{ @"content-type": @"application/x-www-form-urlencoded" };
NSMutableData *postData = [[NSMutableData alloc] initWithData:[@"grant_type=client_credentials" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&client_id=YOUR_CLIENT_ID" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&client_secret=YOUR_CLIENT_SECRET" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&audience=YOUR_API_IDENTIFIER" dataUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/oauth/token"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[request setAllHTTPHeaderFields:headers];
[request setHTTPBody:postData];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"%@", error);
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSLog(@"%@", httpResponse);
}
}];
[dataTask resume];
Was this helpful?
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{yourDomain}/oauth/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER",
CURLOPT_HTTPHEADER => [
"content-type: application/x-www-form-urlencoded"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
Was this helpful?
import http.client
conn = http.client.HTTPSConnection("")
payload = "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER"
headers = { 'content-type': "application/x-www-form-urlencoded" }
conn.request("POST", "/{yourDomain}/oauth/token", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
Was this helpful?
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://{yourDomain}/oauth/token")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/x-www-form-urlencoded'
request.body = "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER"
response = http.request(request)
puts response.read_body
Was this helpful?
import Foundation
let headers = ["content-type": "application/x-www-form-urlencoded"]
let postData = NSMutableData(data: "grant_type=client_credentials".data(using: String.Encoding.utf8)!)
postData.append("&client_id=YOUR_CLIENT_ID".data(using: String.Encoding.utf8)!)
postData.append("&client_secret=YOUR_CLIENT_SECRET".data(using: String.Encoding.utf8)!)
postData.append("&audience=YOUR_API_IDENTIFIER".data(using: String.Encoding.utf8)!)
let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/oauth/token")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
})
dataTask.resume()
Was this helpful?
The response should be similar to the sample below:
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token":"eyJz93a...k4laUWw",
"token_type":"Bearer",
"expires_in":86400
}
Was this helpful?
Token expiration
Your access tokens have a limit for how long the token is valid. Since your communications are on the back-channel, you cannot use refresh tokens to extend sessions, and should consider configuring your access tokens with a 1-hour expiration time. You may need to strike your own balance between security and performance for your specific environment. To learn more, read Update Access Token Lifetime.
Scopes
Before any non-interactive clients or services call your API, you need to define the permissions or Scopes your API allows. You can set the scopes in Auth0 Dashboard to include in your authentication request to Authentication API. To read more examples of ways to use API scopes, read API Scopes.
To configure scopes, follow the instructions on Add API Permissions for Auth0 Dashboard or use the sample provided for Management API.
Branding
Even if you service non-interactive clients or services working on the back-channel, you can still customize your experience to align with the look and feel of your existing brand.
Custom domains
Auth0 supports the use of custom domains when you call the /authorize
endpoint to request access tokens.
M2M Onboarding - custom domains
In Auth0 Dashboard, you must:
Register and verify your domain before you can use it with your Auth0 services.
Determine if you want to manage your own certificate or use an Auth0 managed certificate. To learn more about certificates, read Certificate management options.
Verify the TLS (SSL) version and cipher you want to use for self-managed certificates is supported by Auth0. To learn more, read TLS (SSL) Versions and Ciphers.
To configure your custom domain with Auth0-managed certificates, follow the instructions on Configure Custom Domains with Auth0-Managed Certificates.
If you want to manage your own certificates, follow the instructions on Configure Custom Domains with Self-Managed Certificates.
Review API configuration with custom domains. You may need to adjust your API settings to incorporate a custom domain.
If you experience issues with your custom domain, review Troubleshoot Custom Domains.
Deployment Automation
Auth0 provides support for a couple of different options when it comes to the deployment automation approaches you can use, and each can be used in conjunction with the other.
Best Practice
However you configure deployment automation, we’d recommend you unit test your custom code and Actions prior to deployment, and run some integration tests against your tenant post-deployment too.
Deploy CLI Tool
As recommended under the Architecture section, you should have Auth0 tenants for development, test, and production. These tenants should share identical configurations for quality checks and testing; however, you may be faced with errors as a result of mismatched configurations between your environments. For example, each environment will have different Client IDs and Client Secrets.
To mitigate these mismatch errors, you can use the Deploy CLI Tool to help you integrate your Auth0 instance with your existing CI/CD pipeline. With dynamic keyword replacement, you can replace environmental variables on tenants sharing similar configurations. To learn more, read Deploy CLI Tool and Keyword Replacement.
Real-time Webtask Logs Extension
The Real-time Webtask Logs extension displays all logs for custom code in real-time, including console.log
output and other exceptions. If you are using Auth0 Actions or other custom logic, you can use this extension to debug and troubleshoot. To learn more about installation and configuration, read Real-time Webtask Logs Extension.
Quality Assurance
Quality Assurance is important in identifying issues before you go live. Depending on the nature of your project, there are several different types of quality assurance testing that you’re going to want to consider as part of your integration with Auth0:
How will your APIs perform when subjected to unexpected production loads?
How will your rate limits be affected by third-party applications?
If you are not using Auth0 widgets or features, like Universal Login, you will not have the built-in usability and accessibility best practices out-of-the-box on a host of browsers and devices. To ensure functional requirements are met and unexpected events are handled correctly, guidance is provided for testing the integration between your application(s) and Auth0, and for unit testing individual extensibility modules, such as Auth0 Actions. We also recommend you review Auth0’s penetration testing policy and complete Mock testing you can leverage in conjunction with our load testing policy to help ensure your application(s) perform under unexpected load.
Unit testing
Unit testing is verifying units of extensibility, like Auth0 Actions. If you are using custom code we recommend using a test framework (such as Mocha) to test the additional code before deployment.
Mock testing
In a balance between Auth0’s load testing policy and the desire to load test, it is common practice to create a mock test of Auth0’s endpoints. This is a valuable practice in order to ensure that your configuration works with your expected interfaces without having to restrict your testing, and tools such as MockServer, JSON Server, or even Postman can be used to assist.
Deployment
Our Deploy and Monitor section provides guidance for deployment best practices. We advise your review Pre-Deployment Checks, especially the built-in Auth0 Dashboard Readiness Checks.
To review the Readiness Check, select the drop-down menu below your tenant name and environmental tag at Auth0 Dashboard > Run Readiness Checks.
You can use the filter to apply the Readiness Checks to selected applications. These checks do not apply to your configured APIs.
For checks that do not apply to your specific configuration, you can select Dismiss to remove them from the final results.
We advise you to review Deployment Best Practices for final checks before you go live and take advantage of Logs to monitor your services.