Authorization Code Flow

  • Introduction

    The authorization code grant is meant for web applications where API calls are made from the server. It is the most secure as it involves server-to-server communication, and is also the most functional as it also provides refresh tokens. This allows your application to have indefinite connectivity to the SKY API after the one-time user-interactive consent process.

    The flow starts by redirecting the user's browser from your application to our Authorization URL. The user will login (using their Blackbaud or Google credentials), confirm that it's OK for your application to access their data, and then we'll redirect back to you with an authorization code that you can exchange for an access token. You can store this access token (and the refresh token) in your application, and use it when making API calls on that user's behalf.

    Since this is a redirection-based flow, your application must be able to interact with a web browser and receive incoming requests (via redirection) from our OAuth endpoints.

    We demonstrate this flow in our tutorials and code samples.

    Authorization Code Flow

  • Step 1 – Request authorization

    Initiate the authorization process by redirecting the user's browser to our authorization endpoint. You can choose to do this as a step in your application's login process or in response to some user action in your app (like a button click):

    https://oauth2.sky.blackbaud.com/authorization

    When navigating, you'll need to include a few parameters in the query string. These parameters are fully described in RFC-6749 section 4.1.1:

    Query parameter Description
    client_id Required. The **Application ID** value that we provide when you [register your application](/docs/createapp/). This value uniquely identifies your application. See RFC-6749 section 2.2.
    response_type Required. The value must be set to code.
    redirect_uri Required. The URI to redirect to after the user grants or denies permission to your app. This value must exactly match one of the Redirect URI values you specify when you [register your application](/docs/createapp/), including any capitalization, trailing slashes, etc. See RFC-6749 section 3.1.2.
    state Optional, but recommended. The state parameter is an opaque value that you can provide when requesting authorization that will be echoed back to you when the user grants or denies permission to your app. You can then validate this parameter to ensure that an incoming redirect is the result of an authentication request that originated in your application. This provides protection against Cross-Site Request Forgery (CSRF) attacks. You can also use this parameter to maintain some state between the authorization request you initiate and the incoming navigation to your redirect URI for the purposes of returning the user to tbe most appropriate location within your app. See RFC-6749 section 10.12

    Note: to facilitate local development, we allow the use of _http_ and _localhost_ or the localhost IP (_127.0.0.1_). In production however, we require the use of _https_ for proper security when redirecting.

    A sample authorization request looks like this (with extra line breaks for display purposes only):

    https://oauth2.sky.blackbaud.com/authorization?
    client_id=E140BF29-A528-4048-91A9-83BCB01B7FE2
    &response_type=code
    &redirect_uri=https://www.example.com/oauth2/callback
    &state=fdf80155
  • Step 2 – User authorization

    In this step, we'll ask the user to log in (using their Blackbaud or Google credentials). We'll then ask them if it's ok for your application to access their Blackbaud data:

    Authorization Consent Form

    If the user has access to more than one customer's data, they'll select the customer (tenant) to which they are giving your app permission.

  • Step 3 – User is redirected back

    After the user grants (or denies) your authorization request, we'll redirect the browser to the redirect_uri that you specified in the request (in the above example, we'll redirect the browser back to your application at https://www.example.com/oauth2/callback).

    If the user granted your app permission, the query string will contain the following parameters:

    Query parameter Description
    code An authorization code that can be exchanged for an access token.
    state The value of the state parameter you supplied in the initial authorization request.

    For example (with extra line breaks for display purposes only):

    https://www.example.com/oauth2/callback?
    code=3BB723FF-74C9-4AED-B4F6-7E8A192CBA21
    &state=fdf80155

    If the user denied your permission request, the query string will contain the following parameters:

    Query parameter Description
    error The reason that authorization failed (for example, access_denied).
    state The value of the state parameter you supplied in the initial authorization request.

    For example (with extra line breaks for display purposes only):

    https://www.example.com/oauth2/callback?
    error=access_denied
    &state=fdf80155

    For more information on commonly encountered authorization problems, see common authorization issues.

  • Step 4 – Request tokens

    When your application receives an authorization code, you will need to exchange it for an access token by making a POST request to our token endpoint:

    https://oauth2.sky.blackbaud.com/token

    The body of the request must contain the following fields:

    Field Description
    grant_type Required. This field must contain the value authorization_code.
    code Required. The authorization code supplied to your application's redirect_uri.
    redirect_uri Required. This parameter is used for validation only (there is no actual redirection). The value of this parameter must exactly match the value of the redirect_uri parameter you supplied when initiating authorization.

    In addition, the request must include the following headers:

    Header Description
    Authorization

    Required. Your application's basic authentication credentials. The value of this header must be a base 64-encoded string that contains the application ID and secret that were provided when you registered your application. The value must have the format: Basic <base64 encoded Application ID:Application secret>.

    Note: As an alternative to using the Authorization header, you may supply your application ID and secret as part of the request body as client_id and client_secret parameters, respectively.


    Since this request uses your Application secret, it should be made from the server to avoid exposing the value to the public.

    Content-Type Required. The value should be application/x-www-form-urlencoded.

    For example:

    POST https://oauth2.sky.blackbaud.com/token HTTP/1.1
    Authorization: Basic czZCaGRS...WDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=authorization_code&redirect_uri=https%3A%2F%2Fwww.example.com%2Foauth2%2Fcallback&code=bd2d702f47bc453580098c8076d471b4

    Note: The authorization code expires in 5 minutes. Be sure to quickly exchange it for an access token.

  • Step 5 – Tokens returned

    If the access token request is successful, the response body will contain a JSON object that has the following fields:

    Field Type Description
    access_token string An access token to be used when making calls to the SKY API. The access token should be provided in the standard Authorization header in the form of Bearer token (note the separating space).
    token_type string Indicates the type of token issued, and will always contain the value bearer.
    expires_in integer The time period (in seconds) in which the access token is valid.
    refresh_token string A value that can be used to refresh the access token when it expires. When you exchange a refresh token, you'll receive a new access token (and a new refresh token) that you can use when making subsequent calls to the SKY API. (See refresh access token).
    tenant_id string The ID of the specific Blackbaud customer (tenant) whose data can be accessed using the access token. When the user grants permission to your application, they do so in the context of their organization. The tokens we issue can only be used to access that customer's data. We provide this value to you for informational purposes only - it is not used when calling the SKY API. You may store this value in your application along with the user's access token.
    tenant_name string The name of the specific Blackbaud customer (tenant) whose data can be accessed using the access token. When the user grants permission to your application, they do so in the context of their organization. The tokens we issue can only be used to access that customer's data. We provide this value to you for informational purposes only - it is not used when calling the SKY API. You may store this value in your application along with the user's access token.
    legal_entity_id string The legal entity identifier. A legal entity represents a Blackbaud client (organization or individual) who can try out or purchase the products, services, and solutions Blackbaud provides. We provide this value to you for informational purposes only - it is not used when calling the SKY API. You may store this value in your application along with the user's access token.
    legal_entity_name string The name of the legal entity.
    environment_id string The environment identifier. An environment is a logical group of products and service instances that a legal entity is entitled to. We provide this value to you for informational purposes only - it is not used when calling the SKY API. You may store this value in your application along with the user's access token.
    environment_name string The name of the environment.

    Sample response:

    HTTP/1.1 200 OK
    Cache-Control: no-cache
    Pragma: no-cache
    Content-Length: 918
    Content-Type: application/json;charset=UTF-8
    Expires: -1
    Date: Thu, 10 Sep 2015 15:46:56 GMT
    
    {
      "access_token":"eyJ0eXAiOiJKV1...CTtP0CQ",
      "token_type": "bearer",
      "expires_in": 1199,
      "refresh_token":"eb78ffd...7cb7b",
      "tenant_id": "E27DD7B6-6B71-4689-8B2C-60A74F243966",
      "tenant_name":"Raiser's Edge NXT - Blackbaud (Developer Sandbox)",
      "legal_entity_id":"p-AaBbCcDdEeFfGg987654321",
      "legal_entity_name":"Blackbaud Developer Sandbox"
      "environment_id":"p-abcdef1234567890ABCDEFG",
      "environment_name":"Blackbaud Developer Sandbox Environment"
    }

    If the token request is not successful, the response status code and body will provide details. For more information on commonly encountered authorization problems, see common authorization issues.

  • Step 6 – Call the SKY API

    The access token allows you to make requests to the SKY API on a behalf of a user. When calling the API, provide the access token using the standard Authorization request header with a value of Bearer, followed by a space and the access_token value.

    You will also need to provide your subscription key to the SKY API via the bb-api-subscription-key header. You can use either the primary or the secondary key (both are equally functional), and both can be found on your developer profile page.

    For more information on providing these headers, see request headers.

    Sample Request

    GET https://api.sky.blackbaud.com/constituent/v1/constituents/280 HTTP/1.1
    Host: api.sky.blackbaud.com
    Authorization: Bearer eyJ0eXAiOiJKV1...CTtP0CQ
    bb-api-subscription-key: 77f137116...480d633
    
  • Step 7 – Refresh access token

    For security purposes, access tokens will expire after 60 minutes minutes. When this happens, calls to the SKY API will respond with a status code of 401 Not Authorized along with the message "The required Authorization header was missing or invalid, or the token has expired". To continue making calls to the API, you will need to exchange the value you received in the refresh_token field for a new access token.

    This exchange happens on the server, and does not involve any user interactivity. In this way, your application can have indefinite connectivity to after the initial one-time user-interactive consent.

    To refresh your access token, make a POST request to our token endpoint:

    https://oauth2.sky.blackbaud.com/token

    The body of the request must contain the following fields:

    Field Description
    grant_type Required. This field must contain the value refresh_token.
    refresh_token Required. The refresh token supplied to your application's redirect_uri.

    In addition, the request must include the following headers:

    Header Description
    Authorization

    Required. Your application's basic authentication credentials. The value of this header must be a base 64-encoded string that contains the application ID and secret that were provided when you registered your application. The value must have the format: Basic <base64 encoded Application ID:Application secret>.

    Note: As an alternative to using the Authorization header, you may supply your application ID and secret as part of the request body as client_id and client_secret parameters, respectively.


    Since this request uses your Application secret, it should be made from the server to avoid exposing the value to the public.

    Content-Type Required. The value should be application/x-www-form-urlencoded.

    For example:

    POST https://oauth2.sky.blackbaud.com/token HTTP/1.1
    Authorization: Basic czZCaGRS...WDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=refresh_token&refresh_token=eb78ffdabc7cb7b

    If the refresh token request is successful, the response body will contain a JSON object that has the following fields:

    Field Type Description
    access_token string An access token to be used when making calls to the SKY API. The access token should be provided in the standard Authorization header in the form of Bearer token (note the separating space).
    token_type string Indicates the type of token issued, and will always contain the value bearer.
    expires_in integer The time period (in seconds) in which the access token is valid.
    refresh_token string A value that can be used to refresh the access token when it expires. When you exchange a refresh token, you'll receive a new access token (and a new refresh token) that you can use when making subsequent calls to the SKY API. (See refresh access token).
    tenant_id string The ID of the specific Blackbaud customer (tenant) whose data can be accessed using the access token. When the user grants permission to your application, they do so in the context of their organization. The tokens we issue can only be used to access that customer's data. We provide this value to you for informational purposes only - it is not used when calling the SKY API. You may store this value in your application along with the user's access token.
    legal_entity_id string The legal entity identifier. A legal entity represents a Blackbaud client (organization or individual) who can try out or purchase the products, services, and solutions Blackbaud provides. We provide this value to you for informational purposes only - it is not used when calling the SKY API. You may store this value in your application along with the user's access token.
    legal_entity_name string The name of the legal entity.
    environment_id string The environment identifier. An environment is a logical group of products and service instances that a legal entity is entitled to. We provide this value to you for informational purposes only - it is not used when calling the SKY API. You may store this value in your application along with the user's access token.
    environment_name string The name of the environment.

    Sample response:

    HTTP/1.1 200 OK
    Cache-Control: no-cache
    Pragma: no-cache
    Content-Length: 918
    Content-Type: application/json;charset=UTF-8
    Expires: -1
    Date: Thu, 10 Sep 2015 15:46:56 GMT
    
    {
      "access_token":"azH0eXAiOiJKV1...DTxS1DR",
      "token_type": "bearer",
      "expires_in": 1199,
      "refresh_token":"ab478xsd...7ab6c",
      "tenant_id": "E27DD7B6-6B71-4689-8B2C-60A74F243966",
      "legal_entity_id":"p-AaBbCcDdEeFfGg987654321",
      "legal_entity_name":"Blackbaud Developer Sandbox"
      "environment_id":"p-abcdef1234567890ABCDEFG",
      "environment_name":"Blackbaud Developer Sandbox Environment"
    }

    If the refresh token request is not successful, the response status code and body will provide details. For more information on commonly encountered authorization problems, see common authorization issues.

  • Step 8 – Next steps

    For more information on implementing the authorization code flow, check out our code samples.