Getting an OAuth client ID for use in iOS app

1,025 views
Skip to first unread message

nnhu...@gmail.com

unread,
Apr 18, 2012, 6:39:10 PM4/18/12
to canvas-l...@googlegroups.com
We are wanting to integrate Canvas into our College's iOS app.  In looking at the API docs, it seems to need to obtain a client ID and gives an example of how to do this with Rails.

Is this the only way for our institution to request a client ID?

Roman Visintine

unread,
Apr 18, 2012, 7:03:48 PM4/18/12
to canvas-l...@googlegroups.com
The official way to do this is to use the OAuth flow and have the user enter their username/pass to generate the access token.  The unofficial way that I've used, write a hook to the Canvas DB to set a token directly in database for the user.  This bypasses the need to capture the username/pass from the user which is really useful if you are doing a lot of automated enrollment on the backend before they even get a username/password.

Here is some dirty SQL to do this.  The description is useful so if users stumble upon the access tokens in their profile they will hopefully see what it's for and not delete it.

insert into access_tokens (developer_key_id,user_id,token,purpose) values ('1','1','myt0k3n','iPad app will stop working if deleted');

--Roman

Cody Cutrer

unread,
Apr 18, 2012, 7:11:56 PM4/18/12
to canvas-l...@googlegroups.com
Roman,

That is highly *not* recommended. Instead you can just manually create
an access token in the web UI for your user, and use the as_user_id
parameter on all API requests in order to masquerade as any user (that
the actual user you're using has permissions to masquerade as).
Additionally, it's highly *not* recommended to embed access tokens in
apps that you distribute - anyone could decompile it and use those
credentials maliciously. Also, nnhubbard is referring to the client
id, not the actual access token (you need the former in order to go
through the OAuth flow and get the latter).

nnhubbard,

You'll need a client id for each instance of Canvas you want your app
to talk to. If you're running your own instance, the API documentation
explains how to generate one in script/console (it's a DeveloperKey).
If you want to talk to an instance of Canvas hosted by Instructure,
you'll need to get an API key. You can request one at
http://www.instructure.com/partners.

Cody Cutrer
Software Engineer
Instructure, Inc.

Roman Visintine

unread,
Apr 18, 2012, 7:36:21 PM4/18/12
to canvas-l...@googlegroups.com
Off-topic:
We've been using the masquerade but I've wanted to start using individual access tokens so we don't have hundreds of students unable to access the system due to the one admin account being deleted by accident.  We don't distribute the access token out anywhere, they live on a backend intermediary that handles communications from our app to Canvas.  

--Roman

Mark Suman

unread,
Apr 18, 2012, 7:51:56 PM4/18/12
to canvas-l...@googlegroups.com
Just to clarify, masquerading is mostly meant for batch manipulation of user data from a single admin account. If you are writing integration into an app that individual users will use (like the OP is doing), you will want to use the API to generate individual access tokens for each user. Users can then log into their Canvas accounts and disable access to their data should they lose their device or develop an intense hatred for your Canvas app.

For those wanting to use the API against Canvas Cloud:
1. Go to http://www.instructure.com/partners to get an API key
2. Read the OAuth documentation at https://canvas.instructure.com/
3. Request access tokens through the API
4. Use the generated access token for all further API requests

For those wanting to use the API against their own open source installation:
1. Generate a DeveloperKey in the database. client_id = id of the DeveloperKey. client_secret = api_key of the DeveloperKey.
2. Same as above
3. Same as above
4. Same as above


Mark Suman

Mobile Developer
Instructure Inc.

Cody Cutrer

unread,
Apr 18, 2012, 8:05:06 PM4/18/12
to canvas-l...@googlegroups.com
Roman,

I've very relieved to hear that you're not embedding access tokens in
something that you distribute. Like Mark says, it's very much
preferred to use individual (legitimately created) access tokens. If
you're using single sign-on (SAML or CAS), users won't even need to
log in again if they logged in already via the same SSO to access your
app. If that's not possible, the next recommendation is to use a
single dedicated user for your app. At some point you need to trust
your admins to not delete an account named "Our Custom Integration
User - DON'T DELETE". The problems with what your doing is you'll
need to create a new access token for each new user as they're
created, and you're reaching around Canvas' back to do it. Your app
could break at any time if the data model changes (which it might, as
we improve the API and ability for apps to integrate with Canvas).

Good luck,

Cody Cutrer
Software Engineer
Instructure, Inc.

webm...@puc.edu

unread,
Apr 19, 2012, 1:08:12 PM4/19/12
to canvas-l...@googlegroups.com
Thanks.

Ok, so the easiest way it to just have the user go to the web UI and get their access token?  I just didn't want to have this extra step, as I am not sure all our users would take the time to do that.

How can I have a user login to canvas from our app, and request the access token? Is this possible?


On Wednesday, April 18, 2012 4:11:56 PM UTC-7, Cody Cutrer wrote:
Roman,

That is highly *not* recommended. Instead you can just manually create
an access token in the web UI for your user, and use the as_user_id
parameter on all API requests in order to masquerade as any user (that
the actual user you're using has permissions to masquerade as).
Additionally, it's highly *not* recommended to embed access tokens in
apps that you distribute - anyone could decompile it and use those
credentials maliciously. Also, nnhubbard is referring to the client
id, not the actual access token (you need  the former in order to go
through the OAuth flow and get the latter).

nnhubbard,

You'll need a client id for each instance of Canvas you want your app
to talk to. If you're running your own instance, the API documentation
explains how to generate one in script/console (it's a DeveloperKey).
If you want to talk to an instance of Canvas hosted by Instructure,
you'll need to get an API key. You can request one at
http://www.instructure.com/partners.

Cody Cutrer
Software Engineer
Instructure, Inc.

Mark Suman

unread,
Apr 19, 2012, 1:15:22 PM4/19/12
to canvas-l...@googlegroups.com
You can certainly allow users to enter their credentials in your app and request the access token. That is the preferred way. It would be bad practice to ask all your users to go to the web UI, generate access tokens, and type those into your app. The web UI generation is meant for limited use cases, like one-off scripts and migrations.

Check out this page to learn how to generate access tokens through the API. This is the process that our own iOS apps follow:

Mark Suman

Mobile Developer
Instructure Inc.


Roman Visintine

unread,
Apr 19, 2012, 1:24:46 PM4/19/12
to canvas-l...@googlegroups.com
Pretty easy to do, here is the flow if you did it from the command line, just throw some PHP or whatever you're programming around it and you're ready to go.

Step 1:
We send an initial auth request to canvas w/ an out of band redirect_uri. This will generate an access code that we need to capture.

https://lms.dev.domain.com/login/oauth2/auth?client_id=10&response_type=code&redirect_uri=urn:ietf:wg:oauth:2.0:oob

Step 2:
This will redirect the user to a login page. Once the user logs in using their user/pass they will see a screen stating the application has been authorized for access to their canvas data. The URL bar will contain a code parameter that we need to capture and use in the next step.  In this case the code was... 


e6125fa4389520beb17097608785f7e3046a48e39c3ed11759f82f0b57d977305898be35c686ff918775c087872d9e96975d8b9de741924660ab27de2fac80d0

Step 3:
Using the access code we can then pass that back to Canvas with the full API credentials to generate the access token for the user.

curl -i -H "Accept: application/json" -d "client_id=10&redirect_uri=urn:ietf:wg:oauth:2.0:oob&client_secret=apikeygoeshere&code=e6125fa4389520beb17097608785f7e3046a48e39c3ed11759f82f0b57d977305898be35c686ff918775c087872d9e96975d8b9de741924660ab27de2fac80d0"https://lms.dev.domain.com/login/oauth2/token

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json; charset=utf-8
Date: Wed, 25 Jan 2012 00:56:13 GMT
ETag: "5eb83a92040566cfae389e578b0b48cb"
Pragma: no-cache
Server: Apache/2.2.14 (Ubuntu)
Status: 200
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.11
X-Request-Context-Id: 4d3a8390-291d-012f-d8ea-1231380d4d68
X-Runtime: 79
X-UA-Compatible: IE=edge,chrome=1
Content-Length: 124
Connection: keep-alive

{"user":{"name":"Roman Visintine","id":2},"access_token":"FtDlm909X0xLYPBKD3UofOZ9m1IlPo8RHFKVUy6FMwyQpx4EiavnhVYuCnOkvrzC"}

Step 4: 
Now that we have the access token we can use that to get student resources.

curl -i -H "Accept: application/json" -d "access_token=FtDlm909X0xLYPBKD3UofOZ9m1IlPo8RHFKVUy6FMwyQpx4EiavnhVYuCnOkvrzC"https://lms.dev.domain.com/api/v1/courses/26/discussion_topics/46/entries

HTTP/1.1 201 Created
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json; charset=utf-8
Date: Wed, 25 Jan 2012 01:08:25 GMT
Pragma: no-cache
Server: Apache/2.2.14 (Ubuntu)
Status: 201
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.11
X-Request-Context-Id: 019d41f0-291f-012f-39b3-1231380d4d68
X-Runtime: 315
X-UA-Compatible: IE=edge,chrome=1
Content-Length: 148
Connection: keep-alive

{"id":92,"message":null,"user_id":2,"created_at":"2012-01-24T17:08:25-08:00","updated_at":"2012-01-24T17:08:25-08:00","user_name":"Roman Visintine"}

Hope this helps.

--Roman
Reply all
Reply to author
Forward
0 new messages