External web applications can now log in to Synapse and access users’ identity and resources , with their consent and with a select, limited scope. This is accomplished using a secure and industry-standard protocol called OpenID Connect (OIDC), which is an extension of OAuth 2.0.
Registering and
...
Linking an OAuth 2.0 Client
The details of the Synapse Open ID Connect implementation are published on the web in a standard Open ID Configuration document (aka the “discovery document”): https://repo-prod. prod.sagebase.org/auth/v1/.well-known/openid-configuration. The document includes the web endpoints for registration, authorization, and token generation, as well as the scope of resources that can be requested, and the formats in which Synapse will return information.
All the OAuth clients in Synapse need to be verified after creation and before usage: if a . If an unverified client is used to perform requests, Synapse will prevent their execution replying with a HTTP 403 Forbidden response.
In order to verify an OAuth client please contact synapseinfo@sagebase.org, contact Synapse Help detailing:
Your name
The id ID of the client to be verified (See see below on how to obtain the client idID)
A description of your application
...
An external application can be registered with Synapse as a “client” application by following the steps below. The API reference documents for what follows are here, and the following instructions show how to invoke them from the Python and R clients:
Python
Code Block | ||
---|---|---|
| ||
import synapseclient import json syn = synapseclient.login() client_meta_data = { 'client_name': 'Your client name', 'redirect_uris': [ 'https://yourhost.com/user/login' ], 'client_uri': 'https://yourhost.com/index.html', 'policy_uri': 'https://yourhost.com/policy', 'tos_uri': 'https://yourhost.com/terms_of_service', 'userinfo_signed_response_alg': 'RS256' } # Create the client: client_meta_data = syn.restPOST(uri='/oauth2/client', endpoint=syn.authEndpoint, body=json.dumps(client_meta_data)) client_id = client_meta_data['client_id'] # Generate and retrieve the client secret: client_id_and_secret = syn.restPOST(uri='/oauth2/client/secret/'+client_id, endpoint=syn.authEndpoint, body='') print(client_id_and_secret) |
R
Code Block | ||
---|---|---|
| ||
library(synapser) library(rjson) synLogin() client_meta_data <- list( client_name='Your client name', redirect_uris= list( 'https://yourhost.com/user/login' ), client_uri='https://yourhost.com/index.html', policy_uri='https://yourhost.com/policy', tos_uri='https://yourhost.com/terms_of_service', userinfo_signed_response_alg='RS256' ) # Create the client: client_meta_data<-synRestPOST('/oauth2/client', toJSON(client_meta_data), 'https://repo-prod.prod.sagebase.org/auth/v1') client_id <- client_meta_data$client_id # Generate and retrieve the client secret: client_id_and_secret<-synRestPOST(paste0('/oauth2/client/secret/',client_id), '', 'https://repo-prod.prod.sagebase.org/auth/v1') print(client_id_and_secret) |
The client URI, policy URI, and terms of service URI are optional, as is the userinfo_signed_response_alg
parameteral
parameter. You can optionally include a sector_identifier_uri
parameter, an advanced feature described here, relevant if the client uses multiple hosts since Synapse only returns pairwise
subject values to its OAuth clients.
The returned client_id
and client_secret
will be needed later when getting an access token. The secret is only returned once. (It , and it is not stored in Synapse. ) If lost, you can generate a new secret but the previous one will be invalidated.
You can retrieve, update, and delete your client programmatically using the following commands:
Python
Code Block | ||
---|---|---|
| ||
# Retrieve a client using its ID: client_meta_data = syn.restGET(uri='/oauth2/client/'+client_id, endpoint=syn.authEndpoint) client_meta_data['policy_uri'] = 'https://yourhost.com/updated_policy' # Update a client's metadata: client_meta_data = syn.restPUT(uri='/oauth2/client/'+client_id, endpoint=syn.authEndpoint, body=json.dumps(client_meta_data)) # Delete a client: syn.restDELETE(uri='/oauth2/client/'+client_id, endpoint=syn.authEndpoint) |
R
Code Block | ||
---|---|---|
| ||
# Retrieve a client using its ID: client_meta_data <- synRestGET(paste0('/oauth2/client/',client_id), 'https://repo-prod.prod.sagebase.org/auth/v1') client_meta_data$policy_uri <- 'https://yourhost.com/updated_policy' # Update a client's metadata: client_meta_data <- synRestPUT(paste0('/oauth2/client/',client_id), toJSON(client_meta_data), 'https://repo-prod.prod.sagebase.org/auth/v1') # Delete a client: synRestDELETE(paste0('/oauth2/client/',client_id), 'https://repo-prod.prod.sagebase.org/auth/v1') |
Authenticating with Synapse
To login log in via Synapse your client application should redirect the browser from your application to https://signin.synapse.org
, with the standard OAuth 2.0 request parameters:
...
The ID token is a signed JSON Web Token. The public key(s) used to verify the token signatures are available at the JSON Web Key Set (jwks) URL listed in the OpenID Configuration document. The ID Token contains the requested user identity information. The access token can be used to authorize future requests.
Making Authorized
...
Requests
Access tokens authorize requests to Synapse services. For example, to get an entity’s metadata:
...
where is the value returned from the token endpoint and `syn123456` is replaced with the ID of the entity of interest. As with all available services, [ this service ](https://rest-docs.synapse.org/rest/GET/entity/id.html) is defined in the Synapse [ REST documents](https://rest-docs. synapse.org/rest). The page for each service requiring authorization lists the "Required OAuth Scopes" for the service, i.e., the scope(s) that the access token must have in order to access the service. In this example, the required scope is `view`.
...
If the 'userinfo_signed_response_alg': 'RS256'
option was included in the client registration, then the result will be returned as a signed JSON Web Token, otherwise a simple JSON object will be returned.
To make authenticated requests with the Synapse client:
In Python:
Code Block | ||
---|---|---|
| ||
import synapseclient
syn = synapseclient.Synapse()
syn.login(authToken=<access token>) |
In R:
Code Block | ||
---|---|---|
| ||
library(synapser)
synLogin(authToken=<access token>) |
Refresh Tokens
Access tokens last for 24 hours, after which the client must either repeat the authorization process or use the refresh token to get a new access token. To do the latter, send a request to the refresh token endpoint:
...
Synapse supports an optional scope
parameter which is a down selected list of scopes, reducing the scope of the new access token. The response includes a new refresh token, the previous one being rendered obsolete. Refresh tokens expire 180 days after their last use. As long as a refresh token continues to be used, it will not expire. If a refresh token expires the client can get a new one simply by asking the user to login again.
...
The services described here allow an OAuth client to manage tokens. A separate set of services allow the user to review and revoke refresh tokens that they have granted to an OAuth client. The details are given here. Include Page