Commit a4e84180 authored by Jason Colyer's avatar Jason Colyer
Browse files

Handbook - Switch to using OAuth clients

parent 05039d05
Loading
Loading
Loading
Loading
+90 −18
Original line number Diff line number Diff line
@@ -503,20 +503,46 @@ def base_url
  sandbox? ? 'https://gitlab1707170878.zendesk.com' : 'https://gitlab.zendesk.com'
end

def username
  return ENV.fetch('SB_ZD_USERNAME') if sandbox?
def zendesk_secret
  return ENV.fetch('SB_ZD_SECRET') if sandbox?

  ENV.fetch('ZD_USERNAME')
  ENV.fetch('ZD_SECRET')
end

def token
  return ENV.fetch('SB_ZD_TOKEN') if sandbox?
def zendesk_client_name
  return ENV.fetch('SB_ZD_CLIENT_NAME') if sandbox?

  ENV.fetch('ZD_TOKEN')
  ENV.fetch('ZD_CLIENT_NAME')
end

def auth_string
  Base64.encode64("#{username}/token:#{token}").gsub("\n", '')
def zendesk_client_id
  return ENV.fetch('SB_ZD_CLIENT_ID') if sandbox?

  ENV.fetch('ZD_CLIENT_ID')
end

def zendesk_bearer_token
  @zendesk_bearer_token ||= generate_zendesk_bearer_token
end

def generate_zendesk_bearer_token
  client = Faraday.new(base_url) do |f|
    f.options.timeout = request_timeout
    f.options.open_timeout = open_timeout
    f.headers['Content-Type'] = 'application/json'
  end
  url = 'oauth/tokens'
  response = request_with_retry(client, :post, url, zendesk_bearer_token_payload)
  response['access_token']
end

def zendesk_bearer_token_payload
  {
    'client_id' => zendesk_client_name,
    'client_secret' => zendesk_secret,
    'grant_type' => 'client_credentials',
    'scope' => 'read write'
  }
end

def setup_zendesk_client
@@ -524,7 +550,7 @@ def setup_zendesk_client
    f.options.timeout = request_timeout
    f.options.open_timeout = open_timeout
    f.headers['Content-Type'] = 'application/json'
    f.headers['Authorization'] = "Basic #{auth_string}"
    f.headers['Authorization'] = "Bearer #{zendesk_bearer_token}"
  end
end

@@ -532,6 +558,15 @@ def zendesk_client
  @zendesk_client ||= setup_zendesk_client
end

def revoke_token!
  url = "api/v2/oauth/tokens?client_id=#{zendesk_client_id}"
  tokens = request_with_retry(zendesk_client, :get, url)
  token = tokens['tokens'].detect { |t| t['token'] == "...#{zendesk_bearer_token[-10..]}" }
  return if token.nil?

  request_with_retry(zendesk_client, :delete, "api/v2/oauth/tokens/#{token['id']}")
end

def find_in_collection(collection, attribute, value, collection_name)
  print "[DEBUG] Locating #{collection_name} from #{value}..." if debug

@@ -555,20 +590,46 @@ def base_url
  sandbox? ? 'https://gitlabfederalsupport1585318082.zendesk.com' : 'https://gitlab-federal-support.zendesk.com'
end

def username
  return ENV.fetch('US_SB_ZD_USERNAME') if sandbox?
def zendesk_secret
  return ENV.fetch('US_SB_ZD_SECRET') if sandbox?

  ENV.fetch('US_ZD_USERNAME')
  ENV.fetch('US_ZD_SECRET')
end

def token
  return ENV.fetch('US_SB_ZD_TOKEN') if sandbox?
def zendesk_client_name
  return ENV.fetch('US_SB_ZD_CLIENT_NAME') if sandbox?

  ENV.fetch('US_ZD_TOKEN')
  ENV.fetch('US_ZD_CLIENT_NAME')
end

def auth_string
  Base64.encode64("#{username}/token:#{token}").gsub("\n", '')
def zendesk_client_id
  return ENV.fetch('US_SB_ZD_CLIENT_ID') if sandbox?

  ENV.fetch('US_ZD_CLIENT_ID')
end

def zendesk_bearer_token
  @zendesk_bearer_token ||= generate_zendesk_bearer_token
end

def generate_zendesk_bearer_token
  client = Faraday.new(base_url) do |f|
    f.options.timeout = request_timeout
    f.options.open_timeout = open_timeout
    f.headers['Content-Type'] = 'application/json'
  end
  url = 'oauth/tokens'
  response = request_with_retry(client, :post, url, zendesk_bearer_token_payload)
  response['access_token']
end

def zendesk_bearer_token_payload
  {
    'client_id' => zendesk_client_name,
    'client_secret' => zendesk_secret,
    'grant_type' => 'client_credentials',
    'scope' => 'read write'
  }
end

def setup_zendesk_client
@@ -576,7 +637,7 @@ def setup_zendesk_client
    f.options.timeout = request_timeout
    f.options.open_timeout = open_timeout
    f.headers['Content-Type'] = 'application/json'
    f.headers['Authorization'] = "Basic #{auth_string}"
    f.headers['Authorization'] = "Bearer #{zendesk_bearer_token}"
  end
end

@@ -584,6 +645,15 @@ def zendesk_client
  @zendesk_client ||= setup_zendesk_client
end

def revoke_token!
  url = "api/v2/oauth/tokens?client_id=#{zendesk_client_id}"
  tokens = request_with_retry(zendesk_client, :get, url)
  token = tokens['tokens'].detect { |t| t['token'] == "...#{zendesk_bearer_token[-10..]}" }
  return if token.nil?

  request_with_retry(zendesk_client, :delete, "api/v2/oauth/tokens/#{token['id']}")
end

def find_in_collection(collection, attribute, value, collection_name)
  print "[DEBUG] Locating #{collection_name} from #{value}..." if debug

@@ -600,6 +670,8 @@ end

</details>

You should make sure to run the function `revoke_token!` at the end of your script (or when API connections are no longer needed).

### Connecting to GitLab.com via ruby

When you need to connect to GitLab, use the [starting point](#writing-a-ruby-script) and then add the following:
+6 −0
Original line number Diff line number Diff line
@@ -11,6 +11,12 @@ The [Zendesk Support API](https://developer.zendesk.com/api-reference/ticketing/

### What are Zendesk API tokens

{{% alert title="Warning" color="warning" %}}

Zendesk API token use is [being deprecated](https://support.zendesk.com/hc/en-us/articles/10840968198042-Announcing-the-removal-of-API-tokens-as-an-authentication-method-for-API-requests) 2027-04-30.

{{% /alert %}}

Zendesk API tokens are used in authentication for Zendesk API requests. These tokens are always at the administrator level and cannot be issued at lower permission/role levels. As such, you should always use caution in using and issuing these tokens.

### What are Zendesk integrations
+168 −0
Original line number Diff line number Diff line
---
title: 'OAuth Clients'
description: 'Documentation on OAuth Clients'
---

## Understanding Zendesk OAuth clients

### Grant types

For information on grant types, please see [Zendesk documentation](https://developer.zendesk.com/api-reference/ticketing/oauth/grant_type_tokens/)

Do note we recommend using the [client_credentials](https://developer.zendesk.com/api-reference/ticketing/oauth/grant_type_tokens/#client-credentials-grant-type) grant type.

### Scope

For information on scope, please see [Zendesk documentation](https://developer.zendesk.com/api-reference/ticketing/oauth/grant_type_tokens/#scope)

## Using OAuth clients

The generalized process for using an OAuth client is:

- Generate a bearer token
- Perform your API actions
- Revoke the token

### Generating a bearer token

{{% alert title="Note" color="primary" %}}

- You can only generate these via the API or redirect URL flow. This focuses on using the API as the redirect URL flow can vary from setup to setup.

{{% /alert %}}

To generate a bearer token, you need to know the OAuth client's identifier and secret values. You would then make a POST request to the endpoint `oauth/tokens` with the needed payload.

The payload used should be in the format:

```json
{
  "client_id": "CLIENT_IDENTIFIER",
  "client_secret": "CLIENT_SECRET",
  "grant_type": "client_credentials",
  "scope": "SCOPE VALUES TO USE"
}
```

In the returned body, the `access_token` attribute is what you will use as the bearer token.

### Revoking a bearer token

#### Via the UI

To revoke a bearer token via the UI:

1. Navigate to the admin dashboard for the Zendesk instance
   - [Zendesk Global (production)](https://gitlab.zendesk.com/admin/home)
   - [Zendesk Global (sandbox)](https://gitlab1707170878.zendesk.com/admin/home)
   - [Zendesk US Government (production)](https://gitlab-federal-support.zendesk.com/admin/home)
   - [Zendesk US Government (sandbox)](https://gitlabfederalsupport1585318082.zendesk.com/admin/home)
1. Go to `Apps and integrations > APIs > OAuth clients`
   - [Zendesk Global](https://gitlab.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk Global (sandbox)](https://gitlab1707170878.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk US Government](https://gitlab-federal-support.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk US Government (sandbox)](https://gitlabfederalsupport1585318082.zendesk.com/admin/apps-integrations/apis/oauth-clients)
1. Locate the OAuth client you want to revoke a bearer token for
1. Click the three vertical dots to the right of the OAuth client
1. Click `View tokens`
1. Locate the bearer token to revoke and click the three vertical dots to the right
1. Click `Delete`
1. Click `Delete` on the pop-up to confirm

#### Via the API

To revoke a bearer token via the API, you must know the bearer token's ID. You would then make a DELETE request to the endpoint `api/v2/oauth/tokens/:token_id` (replacing `:token_id` with the bearer token's ID).

In the normal process of generating a bearer token via the API, it is very likely you will not know the generated bearer token's ID. As such, you might need to use what you do know (the OAuth client's identifier and the bearer token itself) to get to that end.

As an example, here is what the process might look like for the OAuth client identifier `test123` with the bearer token `abcdefg123456789`:

```ruby
client_identifier = 'test123'
bearer_token = 'abcdefg123456789'

# Get the OAuth client object

url = 'api/v2/oauth/clients'
oauth_clients = request_with_retry(zendesk_client, :get, url)
client_to_use = oauth_clients['clients'].detect { |c| c['identifier'] == client_identifier }

# Get the bearer token object

url = "api/v2/oauth/tokens?client_id=#{client_to_use['id']}"
tokens = request_with_retry(zendesk_client, :get, url)
token_to_use = tokens['tokens'].detect { |t| t['token'] == "...#{bearer_token[-10..]}" }

# Revoke it

url = "api/v2/oauth/tokens/#{token_to_use['id']}"
request_with_retry(zendesk_client, :delete, url)
```

## Administrator tasks

{{% alert title="Danger" color="danger" %}}

**Security Considerations:**

- OAuth clients are able to perform admin-level tasks and can be extremely dangerous.

{{% /alert %}}

### Creating an OAuth client

To create an OAuth client:

1. Navigate to the admin dashboard for the Zendesk instance
   - [Zendesk Global (production)](https://gitlab.zendesk.com/admin/home)
   - [Zendesk Global (sandbox)](https://gitlab1707170878.zendesk.com/admin/home)
   - [Zendesk US Government (production)](https://gitlab-federal-support.zendesk.com/admin/home)
   - [Zendesk US Government (sandbox)](https://gitlabfederalsupport1585318082.zendesk.com/admin/home)
1. Go to `Apps and integrations > APIs > OAuth clients`
   - [Zendesk Global](https://gitlab.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk Global (sandbox)](https://gitlab1707170878.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk US Government](https://gitlab-federal-support.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk US Government (sandbox)](https://gitlabfederalsupport1585318082.zendesk.com/admin/apps-integrations/apis/oauth-clients)
1. Click `Add OAuth client`
1. Enter the needed information
1. Click `Save`
1. Copy the `Secret` value somewhere (as you will need it for generating bearer tokens)
1. Click `Save`
1. Click `Enforce expiration` to confirm

### Editing an OAuth client

To edit an OAuth client:

1. Navigate to the admin dashboard for the Zendesk instance
   - [Zendesk Global (production)](https://gitlab.zendesk.com/admin/home)
   - [Zendesk Global (sandbox)](https://gitlab1707170878.zendesk.com/admin/home)
   - [Zendesk US Government (production)](https://gitlab-federal-support.zendesk.com/admin/home)
   - [Zendesk US Government (sandbox)](https://gitlabfederalsupport1585318082.zendesk.com/admin/home)
1. Go to `Apps and integrations > APIs > OAuth clients`
   - [Zendesk Global](https://gitlab.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk Global (sandbox)](https://gitlab1707170878.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk US Government](https://gitlab-federal-support.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk US Government (sandbox)](https://gitlabfederalsupport1585318082.zendesk.com/admin/apps-integrations/apis/oauth-clients)
1. Locate the OAuth client you want to edit
1. Click the three vertical dots to the right of the OAuth client and click `Edit`
1. Change the values you wish to change
1. Click `Save`

### Deleting an OAuth client

To delete an OAuth client:

1. Navigate to the admin dashboard for the Zendesk instance
   - [Zendesk Global (production)](https://gitlab.zendesk.com/admin/home)
   - [Zendesk Global (sandbox)](https://gitlab1707170878.zendesk.com/admin/home)
   - [Zendesk US Government (production)](https://gitlab-federal-support.zendesk.com/admin/home)
   - [Zendesk US Government (sandbox)](https://gitlabfederalsupport1585318082.zendesk.com/admin/home)
1. Go to `Apps and integrations > APIs > OAuth clients`
   - [Zendesk Global](https://gitlab.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk Global (sandbox)](https://gitlab1707170878.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk US Government](https://gitlab-federal-support.zendesk.com/admin/apps-integrations/apis/oauth-clients)
   - [Zendesk US Government (sandbox)](https://gitlabfederalsupport1585318082.zendesk.com/admin/apps-integrations/apis/oauth-clients)
1. Locate the OAuth client you want to delete
1. Click the three vertical dots to the right of the OAuth client and click `Delete`
1. Click `Delete client` to confirm the deletion