cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Community Member

Programmatically generate access tokens for users

Jump to solution

I am developing a single page app which will display the calendar information of each student.
I prefer that the student does not need to login to Canvas first (go through the OAuth2 flow).

I am able to proxy the Canvas API request through a secure server which contains the developer key client id and secret.
Due to API Rate Limiting, I would like to generate an access token for the specific user the request is for.
In the following document, it mentions something about programmatically generating the token

https://community.canvaslms.com/docs/DOC-8381-api-rate-limiting 

However I could not find how to do it in the OAuth2 API documentation

OAuth2 Endpoints - Canvas LMS REST API Documentation 

I understand the client_credentials flow is usually for machine to machine. Is there a way to use this for API (non LTI) requests and be limited to a specific user?

Labels (1)
Tags (1)
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Community Advocate
Community Advocate

Hi,

You cannot generate tokens for users. Your application needs to use OAuth2.

From the docs, OAuth2 - Canvas LMS REST API Documentation

Note that asking any other user to manually generate a token and enter it into your application is a violation of Canvas' terms of service. Applications in use by multiple users MUST use OAuth to obtain tokens.

View solution in original post

0 Kudos
5 Replies
Highlighted
Community Member

Here are some code snippets that you may find useful:

@RequestMapping(value = { "/beginOauth" }, method = { RequestMethod.GET, RequestMethod.POST })
public String startOauth(HttpServletRequest request) {
logger.debug("in beginOauth");
String randomUuid = UUID.randomUUID().toString();

StringBuilder sb = new StringBuilder();
sb.append("redirect:");
sb.append("https://");
sb.append("princeton.beta.instructure.com");
sb.append("/login/oauth2/auth");
sb.append("?");
sb.append("client_id=");
sb.append(Constants.CLIENT_ID);
sb.append("&state=");
sb.append(randomUuid);
sb.append("&response_type=code");
sb.append("&redirect_uri=");
sb.append("http://localhost:3010");
sb.append("/oauthResponse");
logger.debug("returning from start oauth: " + sb.toString());
return sb.toString();
}

@RequestMapping("/oauthResponse")
public String oauthResponse(HttpServletRequest request, @ModelAttribute(value = "code") String oauthCode,
@ModelAttribute(value = "state") String state, @ModelAttribute(value = "error") String errorMsg)
throws Exception {

if (oauthCode != null && !oauthCode.trim().isEmpty()) {
try {
logger.debug("got oauth code back: " + oauthCode);
URL tokenUrl = new URL("https://princeton.beta.instructure.com" + "/login/oauth2/token");
HttpURLConnection con = (HttpURLConnection) tokenUrl.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
OutputStream out = null;
try {
out = (OutputStream) con.getOutputStream();
} catch (Exception ex) {
logger.error(ex.toString());
}
StringBuilder paramsBuilder = new StringBuilder();
paramsBuilder.append("client_id=");
paramsBuilder.append(Constants.CLIENT_ID);
paramsBuilder.append("&client_secret=");
paramsBuilder.append(Constants.CLIENT_KEY);
paramsBuilder.append("&code=");
paramsBuilder.append(oauthCode);
paramsBuilder.append("&redirect_uri=");
paramsBuilder.append("http://localhost:3010");
paramsBuilder.append("/oauthResponse");
logger.debug("sending params to get oauth token: " + paramsBuilder.toString());
out.write(paramsBuilder.toString().getBytes());
out.flush();
out.close();

int responseCode = con.getResponseCode();
logger.debug("got response code from token request: " + responseCode);
logger.debug("response message: " + con.getResponseMessage());

BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
logger.debug("content: " + content.toString());
JsonObject jobj = new Gson().fromJson(content.toString(), JsonObject.class);
String accessToken = jobj.get("access_token").getAsString();
String refreshToken = jobj.get("refresh_token").getAsString();

} catch (IOException e) {
logger.error("error getting oauth token", e);
}
}
return "redirect:http://localhost:3010/hello";
}
0 Kudos
Highlighted
Community Advocate
Community Advocate

Hi,

You cannot generate tokens for users. Your application needs to use OAuth2.

From the docs, OAuth2 - Canvas LMS REST API Documentation

Note that asking any other user to manually generate a token and enter it into your application is a violation of Canvas' terms of service. Applications in use by multiple users MUST use OAuth to obtain tokens.

View solution in original post

0 Kudos
Highlighted

Thanks carroll-ccsd‌, I was aware we shouldn't manually generate them via the UI. I was wondering if an admin user has a token via OAuth2, that they could then programmatically generate a user token, i.e via a request. I guess that goes against the principals of OAuth2, but perhaps it can be done with JWT/JWKs similar to the LTI authentication.

Edit: on second thought I get whether its via the UI or programmatically, it is the same issue, we shouldn't generate tokens for users.

0 Kudos
Highlighted
0 Kudos
Highlighted

Mohamed,

Let me know if you have any further question. You will need to setup the redirect URL on the developer key setting page.

Good luck!

Kim Huang

Package Adoption and Configuration |OIT

Princeton University

701 Carnegie Center, 234J

Princeton, NJ 08540

(609)258-8532

0 Kudos