Skip to content

API Integration Guide: OAuth 2.0 & Canvas LMS

The OAuth 2.0 protocol provides a secure mechanism for a third-party application (the Client) to access user information stored in Canvas LMS without requiring the user to share their Canvas credentials directly.

When an instructor links their account with a third-party application, they are redirected to the Canvas SSO login page. Upon successful authentication and consent, the application is granted authorized access to the instructor’s Canvas data. This linked state enables core integrations, such as importing student rosters and exporting grades seamlessly.


Understanding OAuth 2.0 requires defining the specific roles each system component plays:

  • Resource Owner: The end-user (e.g., the instructor) who grants access to their data.
  • Client: Your application requesting access to the user’s information.
  • Authorization Server: The system that authenticates the user and issues access tokens. Canvas LMS acts as the authorization server.
  • Authorization Grant: A credential representing the resource owner’s consent. The client exchanges this grant with the authorization server for an access token.
  • Access Token (Bearer Token): The secure key used by the client to access protected resources.
  • Resource Server: The system hosting the protected user accounts and information. It verifies the access token before responding to requests.
  • Redirect URI: The pre-registered destination where the authorization server sends the user after granting consent.
  • Scope: The specific permissions granted by the end-user (e.g., reading course lists, fetching enrollments).
  • Client ID & Client Secret: The unique credentials used to identify and authenticate your application to the authorization server.

Canvas LMS implements the Authorization Code Flow, which is the most common and secure OAuth 2.0 flow for server-side applications. The process is divided into front-channel (browser-based) and back-channel (server-to-server) communications.

sequenceDiagram
    participant User as Resource Owner (Instructor)
    participant Client as Client Application
    participant AuthServer as Authorization Server (Canvas)
    participant ResourceServer as Resource Server (Canvas)

    Note over User, AuthServer: Front-Channel Flow
    User->>Client: Initiates account linking
    Client->>User: Redirects to Canvas Authorization URL
    User->>AuthServer: Enters credentials & grants consent
    AuthServer->>User: Redirects to Client Redirect URI with Auth Code
    User->>Client: Passes Auth Code via Redirect

    Note over Client, ResourceServer: Back-Channel Flow
    Client->>AuthServer: POST Auth Code, Client ID, Client Secret
    AuthServer-->>Client: Returns Access Token & Refresh Token
    Client->>ResourceServer: API Request + Access Token
    ResourceServer-->>Client: Returns Requested Data
Section titled “1. Requesting User Consent (Front-Channel)”

To begin the flow, your application redirects the user’s browser to the Canvas authorization endpoint: GET https://<canvas-instance>/login/oauth2/auth

Include the following query parameters:

  • client_id: Your application’s unique ID.
  • response_type: Set to code.
  • redirect_uri: The endpoint in your application that will handle the callback.
  • scope: (Optional) A space-separated list of required scopes.

The user logs into Canvas and is prompted to authorize the application. Upon consent, Canvas redirects the user back to the redirect_uri, appending a temporary authorization code to the URL query string (?code=...).

2. Exchanging the Code for a Token (Back-Channel)

Section titled “2. Exchanging the Code for a Token (Back-Channel)”

Your application extracts the authorization code and securely sends a background POST request to the Canvas token endpoint: POST https://<canvas-instance>/login/oauth2/token

Include the following JSON payload or form data:

  • grant_type: Set to authorization_code.
  • client_id: Your application’s unique ID.
  • client_secret: Your application’s secure secret key.
  • redirect_uri: Must exactly match the URI used in step 1.
  • code: The authorization code received from the redirect.

Canvas validates the credentials and returns a JSON response containing the access_token, a refresh_token, and the expires_in duration (typically 3600 seconds).

Your application stores these tokens securely and utilizes the access_token in the Authorization header of subsequent API requests to the Canvas Resource Server.

GET /api/v1/courses HTTP/1.1
Host: <canvas-instance>
Authorization: Bearer <access_token>

Access tokens possess a limited lifespan. Before making API calls, your application should validate the token’s temporal validity. If the token is expired, issue a refresh request to the token endpoint: POST https://<canvas-instance>/login/oauth2/token

Include the following payload:

  • grant_type: Set to refresh_token.
  • client_id: Your application’s unique ID.
  • client_secret: Your application’s secure secret key.
  • refresh_token: The refresh token received in step 2.

Upon success, the new access_token and updated expiration timestamp should be persisted to your database.


To demonstrate this within a Java environment, the following snippet illustrates a basic Spring Boot service handling the back-channel token exchange using Spring’s RestTemplate.

package com.example.canvasintegration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
@Service
public class CanvasOAuthService {
@Value("${canvas.client-id}")
private String clientId;
@Value("${canvas.client-secret}")
private String clientSecret;
@Value("${canvas.redirect-uri}")
private String redirectUri;
private final RestTemplate restTemplate = new RestTemplate();
/**
* Exchanges the front-channel authorization code for a Canvas access token.
*/
public CanvasTokenResponse exchangeCodeForToken(String code) {
String tokenUrl = "https://canvas.instructure.com/login/oauth2/token";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("grant_type", "authorization_code");
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
map.add("redirect_uri", redirectUri);
map.add("code", code);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
// Perform the POST request to the Authorization Server
return restTemplate.postForObject(tokenUrl, request, CanvasTokenResponse.class);
}
}

This service can then be injected into your web controllers to handle the callback endpoint where the user is redirected after granting consent.