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
email 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:

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:

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.