Dartmouth API Developer Portal
DartAPI Login Service (Authentication)
Jwt
Notes on usage
Data available through the DartAPI is authorized via the use of "scopes" (aka roles) that are granted to your API consumer service account. Some APIs are open to public (ie. Dartmouth affiliated entities). Others require certain levels of scopes granted to the service account in order to return more sensitive data. In each API's documentation the required scopes needed to return data through the API are documented clearly in a "required scopes" section.
Scopes are requested through an optional query parameter called "scope". Only scopes that are granted to the service account can be returned (ie. you must have been granted the scope in order for the request to be satisfied). To ensure that the scopes you have requested have been granted, you should examine the return payload of the jwt call and ensure the "accepted_scopes" attribute contains the scopes you believe are needed to use the subsequent API calls successfully.
Note that there is no "default" action on a call to /api/jwt to return all your scopes. Service accounts may have 10's or even 100's of granted scopes, many of which do not pertain to accessing APIs. The jwt should be as small as possible to limit the overhead of passing and decoding the jwt with each call. Therefore it is the responsibility of the consumer to pass in the needed scopes and in turn should check that all requested scopes have been "accepted" before proceeding.
To call /api/jwt with multiple scopes use a space separated list. Some languages and API tools will URL encode a URL with spaces properly by default. In other languages it may be necessary to take an extra step to url encode properly. Below is an example Postman request with 2 scopes specified.
https://api.dartmouth.edu/api/jwt?scope=urn:dartmouth:employees:read.sensitive urn:dartmouth:people:read.sensitive
Request
POST /api/jwt
Required Headers
Authorization: {api_key}
The {api_key} for the login is passed as a header in the POST call. The api key is provided when access to DartAPI is approved.
Example
Authorization: TnNfZyRYKkkwJG4xMENxS3lPSDkyMzRKTG5FbzhFVSNGdjNBQXBwVTZUREpwMFlyc2FFSE5vYzBIWlM2dHN6V29mNG0zYSpDYUNReGJoQyEoUGE2MGEhU1VfaGgqYktRMl5ndthisisObviouslyNotAValidKeyd0ZacXEkWihhOWdram56akxhWkJrT2FuYkpWc05EUUdWRW1eXkFUbEdmIzk0JDl2a0U4M0hMNUNhIXk3S0ZpZVFpT1VBIQo=
Parameters
Parameter Name | Type | Description | Valid values | Required |
---|---|---|---|---|
scope | string | provides the login service a list of "requested scopes" that should be included in the return jwt payload | optional |
Returns
Status Code | Description |
---|---|
200 | Generation of the jwt has been successful |
Field | Type | Description |
---|---|---|
jwt | string | the jwt is an encoded parcel that contains information about the caller of the api and authorization scopes |
payload | object | the decoded jwt which allows you to inspect the contents of the jwt (see description next section) |
accepted_scopes | array | an array of the scopes that were accepted in the login request |
Sample Request
https://api.dartmouth.edu/api/jwt?scope=urn:dartmouth:general_ledger:write.transaction
Sample Return
{
"jwt": "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1MjE2NjExNTAsImlhdCI6MTUyMTYzOTU1MCwic3ViIjoiZjAwM2doYyIsImlzcyI6Imh0dHBzOi8vYXBpLXByZXByb2QuZGFydG1vdXRoLmVkdS9hcGkvand0IiwiYXVkIjoiaHR0cHM6Ly9hcGktcHJlcHJvZC5kYXJ0bW91dGguZWR1IiwibmFtZSI6IkludGVncmF0aW9uIFRlc3QgVXNlciIsImVtYWlsIjoiSW50ZWdyYXRpb24uVGVzdC5Vc2VyQERhcnRtb3V0aC5lZHUiLCJzY29wZSI6InVybjpkYXJ0bW91dGg6Z2VuZXJhbF9sZWRnZXI6d3JpdGUudHJhbnNhY3Rpb24ifQ.wCRWfAL8_PS6VekRNDVCsD-CNFjoV0uyJy5ZURzUP4qgcoQP50ZLDhdakRLa3KG8p6JDKur8MlFiSZg0yvspqUO6XGV1JvwgNw_YUmW6Z30amV-lUF9vP-5jTS0h1QO9tnagf3h7iwzqSVJouQcaF5Q4o4_x0-0z30ES-WAO0uo8vmcoVLAMQ1EGXxr4BuEDjVqreMkiI32BIMuPOmbAciQDKXCZxzoQxPMFXx2dXQGiXToroxiIDeVkkLdbgb-wErrUhSMnez8nwDN_XmEi-3JKaSuncef4-y9Kzn225CkQBFL7FePlWQfkf8JjNB5kEhnBE1ZVz8MbWjt1N9WvMQ",
"payload": {
"sub": "f004ghc",
"aud": "https://api.dartmouth.edu",
"scope": "urn:dartmouth:people:private",
"iss": "https://api.dartmouth.edu/api/jwt",
"name": "Joe User",
"exp": 1522286039,
"iat": 1522264439,
"email": "Joe.A.User@Dartmouth.edu"
},
"accepted_scopes": [
"urn:dartmouth:general_ledger:write.transaction"
]
}
Decoded jwt
By visiting jwt.io and pasting in the returned jwt field, it is possible to see what is "inside" the jwt. Here is an example:
{
"exp": 1521495686,
"iat": 1521474086,
"sub": "fz00ght",
"iss": "https://api.dartmouth.edu/api/jwt",
"aud": "https://api.dartmouth.edu",
"name": "Joe API User",
"email": "Joe.Api.User@Dartmouth.edu",
"scope": "urn:dartmouth:general_ledger:write.transaction"
}
Field | Type | Description |
---|---|---|
exp | number | exp is an integer counting seconds from Unix epoch |
iat | number | exp is an integer counting seconds from Unix epoch |
sub | string | subject of the jwt i.e. the identity associated with the api key presented to the service |
iss | string | issuer of the jwt |
aud | string | audience of the jwt, i.e. the environment that will accept the jwt on subsequent calls |
name | string | name associated with the identity of the caller |
string | email address associated with the identity of the the caller | |
scope | string | comma separated list of scopes contained within the jwt |
Authorization Overview
Authorization to APIs are granted at several levels. The Login API which authenticates the calling entity (user) requires a valid Dartmouth Account (typically a service account...eventually OAUTH accounts will be supported) which can generate a self service "API Key" through this portal. An API key alone means the user falls into an Authenticated
authorization level.
Once authenticated access to APIs is authorized through scopes or "roles" maintained in the Dartmouth directory. For all APIs there are three basic levels of access for both read and write operations for each resource:
- Authenticated
- Sensitive
- Highly Sensitive
Note that these levels are independent, there is no inheritance of authorization from lower levels. For example using a Highly Sensitive scope only incrementally adds additional attributes to a payload, it does not also include the attributes that enforce authorization at the Sensitive level. To get attributes from both levels, both scopes would need to be specified.
Additionally there are separate roles for access to particular functions. Examples are:
- Private User Viewers - allows access to confidential identities
- General Ledger Transaction Creators - allows posting transactions to GL
- View Photo Users - access to lenel photos
For read (GET) resources scopes can enforce authorization to particular resource records (think rows) and to particular attributes (think columns).
See documentation for each Resource API for details on required scope necessary to see resource information.