OAuth

Using OAuth 2.0 with Onshape

Introduction

OAuth 2.0 (“OAuth”) is an authorization framework allowing a user (also referred to as the resource owner) to approve client application access to the user’s resources at an OAuth-enabled server.

When integrating with Onshape, OAuth tokens authorize third-party applications (such as a desktop application or a web service) for limited access to users’ Onshape documents. Using OAuth terminology, Onshape acts as both the authorization and resource server, while the desktop or web-based application is the client. Resource owners have the option of granting or denying access to applications.

RFC 6749 (http://tools.ietf.org/html/rfc6749) is the reference for the OAuth framework as a whole. Most of this document describes how to implement the OAuth exchanges described by the reference within the context of Onshape and client applications. RFC 6750 (http://tools.ietf.org/html/rfc6750) describes the exchange of OAuth access tokens between clients and OAuth servers.

Once obtained an OAuth token will work for third-party APIs under /api. It’s not appropriate to attempt to use an OAuth token to fetch the URLs typically displayed in a web browsers location bar.

Application Registration

OAuth relies on an orchestrated set of interactions between the web browser, Onshape’s web services and third-party client applications (which may be desktop or web server-based). The orchestration takes the form of a sequence of requests and subsequent browser redirections between pre-configured URL endpoints. In order to take part in the OAuth process an application must first be registered with Onshape.

Currently partners register applications by contacting api-support@onshape.com to register OAuth application. The following items are necessary:

  1. Application name - acceptable names must include some identification of the partner. ‘Megacorp STL Previewer and Editor’ is appropriate, but ‘STL Preview and Editor’ is not. This value cannot be changed after the application is registered.

  2. Application description - a short string displayed to the user when they’re asked to grant your application permission to access their data.

  3. Primary format - this string uniquely identifies your application and is a marker for the data it might store on Onshape servers. It should take the form of a Java style reverse domain name: com.megacorp.stl-preview. This value cannot be changed after the application is registered.

  4. Redirect URIs - Your application must specify at least one (but multiple values are acceptable) URI used in OAuth protocol exchanges. This URL must also use SSL (a URL that begins with https), with two exceptions applicable for installed desktop applications. These two are exceptions allow redirect URIs of the form http://localhost:<port>, or the URN string urn:ietf:wg:oauth:2.0:oob. The ’localhost’ and URN string are meant for installed desktop applications since they do not require a publicly reachable server to be part of the OAuth process. Possible reasons for specifying more than one redirect URI is if you deploy “test” and “production” versions of your application, and want to use a specific version of your application for different sets of users.

  5. Application Scope (Permissions) - the application should also indicate the type of access it requires to the user’s data. The current list of scopes are:

  • Read - Application has read access to your documents
  • Comment - Application has read and comment access to your documents
  • Write - Application has modify and comment access to your documents
  • Reshare - Application has modify and share access to your documents
  • Full - Application has full access to your documents

The list of scopes may be increased or adjusted in the future, in particular access to personal information such as a users email address will be placed under a new scope that will need to be explicitly requested.

  1. OAuth URL - this URL is the ‘authentication page’ for your application. This is the first URL called from an Onshape application’s page. The page hosted at this URL should handle OAuth authentication (see “Obtaining a code”, below). Once your application’s server is authenticated on behalf of the user, the user should be redirected to your application’s content. If Onshape passes the redirectOnshapeUri attribute in the first redirect (as a query parameter) in the OAuth flow, the app should redirect to the URI passed in this attribute after a successful grant. Legacy support: As we migrate to extension based apps, the old Iframe URL is moved to a tab based extension. Change as needed to provide a better user experience.

After the application has been registered Onshape will send you corresponding OAuth Client ID and OAuth Client Secret strings. While the Client ID is considered public - it is how your specific application is uniquely identified in OAuth protocol exchanges - the Client Secret must be stored securely. For example, it should not be checked in to source code control systems. Protect the Client Secret as you would any password data.

Obtaining an OAuth Access Token

An OAuth access token is the credential a client application uses to access user resources at Onshape. Obtaining an OAuth access token is a two-part process: first obtaining a one-time use authorization code, and then exchanging the authorization code for them access token. The access token is used for all subsequent Onshape requests, though it too has a limited lifetime (which may be refreshed, as described below).

In the example URLs used below to describe the OAuth exchanges, values enclosed in angle brackets (’<>’) are descriptive names used to indicate that application-specific values should be substituted in actual exchanges. All other URLs and URL fragments are literal strings.

Obtaining a code

Your application must first must direct the user to https://oauth.onshape.com/oauth/authorize?response_type=code&client_id=<your client id>. You may optionally add the redirect_uri, scope, state and company_id query parameters.

If your application was registered with more than one redirect URI, then the specific URI to use is indicated by the redirect_uri query string. You can only use a redirect_uri value that has been previously registered for this application. URIs must be a exactly match registered values, including the port number (if not using the default HTTPS port). Typically this action is performed by using a HTTP 302 response code with a Location HTTP response header when the user arrives at the starting page of your application, for example in response to a GET of the Base HREF specified in the application registration. The Location HTTP response header should contain the URL with the correct query parameters as outlined above.

If the scope parameter is omitted the token retrieved at the end of this process will be valid for all scopes your application has registered. You can restrict the token to a subset of the registered scopes by using the scope parameter. Refer to section of RFC 6749 for the exact syntax to specify scopes within a query string. Again, this is optional; by default the OAuth exchange will use the scopes registered for your application.

The state parameter is a string value supplied by the partner server and returned back to the partner server later when the browser is redirected to the supplied redirect URI. It can be useful to encode such information as the document and workspace ID from the URL that initiates the OAuth process into the state parameter.

The company_id parameter identifies the specific Onshape company of the user requesting the token. OAuth tokens are unique to the combination of user and company. If the user is a member of more than one company and the company_id parameter is not supplied the user will automatically be prompted to select from a list of eligible companies. Integrated applications are supplied with a company identifier alongside other initial startup parameters for the document the app is installed against when they’re first loaded.

Note this should be a GET operation and should supply all the values as URL encoded query parameters. In particular the OAuth client id typically has at least one trailing = which must be URL encoded (replaced with %3D in the query parameter) in order to be handled correctly.

When the browser fetches the redirected https://oauth.onshape.com/oauth/authorize URL the user may be prompted to login (if the used is not currently logged in to Onshape) and is presented with a page describing your application and the scopes that it is requesting. The user can choose to Grant or Deny the request - after this choice is made the browser is redirected to the location specified by the redirect_uri if present in the request, or the default location entered during application registration.

The redirection will cause the browser to GET https://<redirect_uri>?code=<code>&state=<state> (if no state value was supplied initially it will be omitted in this GET). If an error occurs the browser is redirected to https://<redirect_uri>?error=<error_code>&state=<state> A list of possible error codes is given at section 4.1.2.1 of RFC 6749. If the user denies your application access then the error_code will be access_denied though other values may also be encountered.

At this point your web server application should extract the code query string parameter value and use it in the subsequent phase to obtain an access token. This authorization code is a one-time use token, and is valid for only a short duration. If the code is not exchanged for an access token within 60 seconds after it is issued, it expires.

Exchanging the code for a token

Using the authorization code from the above exchange, your application can now obtain the OAuth access token. The application makes a POST HTTP request to https://oauth.onshape.com/oauth/token, with the following data provided as a URL-encoded form body with Content-Type application/x-www-form-urlencoded:

grant_type=authorization_code&code=<code>&client_id=<client id>&client_secret=<client_secret>

Additionally if a redirect URI was supplied as an additional parameter in the initial GET of /oauth/authorize it must also be supplied here.

Note Each parameter must be URL encoded - as before the client ID and client secret both have trailing = which must be replaced with %3D. Do not encode the entire body of the POST request - the = separating parameter name and value must be left intact. This is a POST operation with the body of the POST message containing the data to complete the OAuth request for an access token. It is not a GET operation with the additional data supplied as query parameters.

In response to a valid POST request the server returns a JSON encoded structure:

{
  "access_token":"<access token>",
  "token_type":"Bearer",
  "expires_in":3600,
  "refresh_token":"<refresh token>",
}

This token structure can be stored by your server as data unique to the user who initiated the request or you can make it part of the server side session storage for this users session with your server.

Using the access token

The ‘access_token’ must be supplied on all subsequent Onshape API requests as a header value: Authorization: Bearer <access_token> The access token uniquely identifies the combination of your application, the Onshape user and the set of permissions granted for the access token.

The access token has a limited lifetime of 60 minutes, after which it will no longer work and attempts to use it will result in an error response for an Onshape API request. The application must use the refresh token returned by the original authorization code exchange to generate new access tokens

Refreshing the access token

When the access token expires it must be refreshed by making another POST request to https://oauth.onshape.com/oauth/token with the following URL encoded form body (again, with Content-Type application/x-www-form-urlencoded):

grant_type=refresh_token&refresh_token=<refresh_token>&client_id=<client_id>&client_secret=<client_secret>.

As with the authorization code data, the parameters in the form body must be URL encoded. The response to this POST request will be a JSON encoded structure as before with a new access_token value that can be used for the next 60 minutes.

Refresh tokens are valid for the lifetime of the user’s grant. If a user who has previously granted access to your application decides to revoke the grant, the refresh token is invalidated. If the user decides to re-grant application access, a new refresh token is generated and returned along with the access token.

Notes for developers of installed desktop applications

OAuth is designed for interactions between two servers utilizing a browser. However it can also be used by an installed desktop (or mobile) application. The application must perform a similar role to that of a third party server - it must exchange the code for an access token structure.

In order to enable this to be as automatic as possible Onshape allows two special forms of redirect URI to be registered: http://localhost:<port> and urn:ietf:wg:oauth:2.0:oob

The first causes the browser to attempt to load a page from the host upon which it is running. The code parameter etc will be supplied exactly the same as outlined above. If the application can listen on the registered port and behave as a simple web server for the redirect URI it can retrieve the code in the same way as a deployed web server would.

The second will cause the browser to display a simple page containing the code after a request has been granted instead of going to a new URI. The page contains simple instructions to copy and paste the code into an application field. The browser will also update the title of the window to contain the code. An application could also look for browsers with window titles containing the string Success code=<code> and automatically grab the code from the browser window title. If an error occurs (the grant is denied for example) then the browser window title will contain Error description=<error string>

Notes for debugging

Debugging OAuth can be a little tricky. Here are some things to bear in mind:

  1. Make sure you are correctly URL encoding the values supplied to the oauth/authorize and oauth/token endpoints.

  2. Use a GET /oauth/authorize but a POST /oauth/token and make sure that the GET uses query parameters but that the POST uses a URL encoded form body.

  3. If you supply a redirect_uri to /oauth/authorize you must also supply it as an additional parameter in the POST to /oauth/token

  4. Use a tool such as Burp (https://portswigger.net/burp) or Charles (http://charlesproxy.com) to deliberately ‘man-in-the-middle’ the connection requests between your server and Onshape, and verify that you are performing the correct REST operations (GET vs. POST) and correctly URL encoding the parameter values.