Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/integration_tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Integration Tests

on:
pull_request:
branches: [main]
push:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Run integration tests
env:
API_BASE_URL: ${{ vars.API_BASE_URL }}
SERVICE_ID: ${{ vars.SERVICE_ID }}
SERVICE_TOKEN: ${{ secrets.SERVICE_TOKEN }}
ORG_TOKEN: ${{ secrets.ORG_TOKEN }}
run: bundle exec rake test
35 changes: 35 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Tests

Integration tests that run against a live Authlete API server. Each test creates and deletes its own OAuth client within a shared service.

## Prerequisites

- A running Authlete API server (cloud or self-hosted)
- A service and service access token
- Dependencies installed: `bundle install`

## Run tests

```bash
API_BASE_URL="<url>" \
SERVICE_ID="<id>" \
SERVICE_TOKEN="<token>" \
ORG_TOKEN="<org-token>" \
bundle exec rake test
```

Single file (`-v` for verbose):

```bash
API_BASE_URL="<url>" SERVICE_ID="<id>" SERVICE_TOKEN="<token>" \
bundle exec ruby -Itest test/auth_grant_test.rb -v
```

## Environment variables

| Variable | Required | Description |
|---|---|---|
| `API_BASE_URL` | Yes | Authlete API URL (e.g. `https://us.authlete.com`) |
| `SERVICE_ID` | Yes | Numeric service ID |
| `SERVICE_TOKEN` | Yes | Service access token |
| `ORG_TOKEN` | No | Org-level token for managing service/client settings. Falls back to `SERVICE_TOKEN`. |
119 changes: 119 additions & 0 deletions test/auth_grant_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# frozen_string_literal: true

require_relative 'test_helper'

class AuthGrantFlowTest < Minitest::Test
include SdkHelper

def setup
@service_id = SERVICE_ID
@mgmt_authlete_client = create_sdk_client(MGMT_TOKEN)
@authlete_client = create_sdk_client(SERVICE_TOKEN)
@mgmt_authlete_client.services.update(
service_id: @service_id,
service: Authlete::Models::Components::ServiceInput.new(
access_token_duration: TOKEN_DURATION_SECONDS
)
)
@client = create_test_client(@mgmt_authlete_client, @service_id)
@client_id = @client.client_id.to_s
@client_secret = @client.client_secret
end

def teardown
@mgmt_authlete_client.clients.destroy(service_id: @service_id, client_id: @client_id) if @client_id
end

def test_authorization_code_flow
# --- Step 1: Authorization Request ---
encoded_redirect = URI.encode_www_form_component(REDIRECT_URI)
parameters = "response_type=code&client_id=#{@client_id}" \
"&redirect_uri=#{encoded_redirect}" \
"&state=#{STATE}"

auth_request = Authlete::Models::Components::AuthorizationRequest.new(
parameters: parameters
)
response = @authlete_client.authorization.process_request(
service_id: @service_id,
authorization_request: auth_request
)

auth_resp = response.authorization_response
assert_equal 'INTERACTION', auth_resp.action.serialize,
"Expected INTERACTION action, got #{auth_resp.action}"

ticket = auth_resp.ticket
refute_nil ticket, 'Authorization ticket must not be nil'

# --- Step 2: Authorization Issue (simulate user consent) ---
issue_request = Authlete::Models::Components::AuthorizationIssueRequest.new(
ticket: ticket,
subject: SUBJECT
)
response = @authlete_client.authorization.issue_response(
service_id: @service_id,
authorization_issue_request: issue_request
)

issue_resp = response.authorization_issue_response
assert_equal 'LOCATION', issue_resp.action.serialize,
"Expected LOCATION action, got #{issue_resp.action}"

auth_code = issue_resp.authorization_code
refute_nil auth_code, 'Authorization code must not be nil'

assert_includes issue_resp.response_content, 'code=',
'Response content must contain code='
assert_includes issue_resp.response_content, "state=#{STATE}",
'Response content must contain state='

# --- Step 3: Token Request ---
token_request = Authlete::Models::Components::TokenRequest.new(
parameters: "grant_type=authorization_code" \
"&code=#{auth_code}" \
"&redirect_uri=#{encoded_redirect}",
client_id: @client_id,
client_secret: @client_secret
)
response = @authlete_client.tokens.process_request(
service_id: @service_id,
token_request: token_request
)

token_resp = response.token_response
assert_equal 'OK', token_resp.action.serialize,
"Expected OK action for token, got #{token_resp.action}"

access_token = token_resp.access_token
refute_nil access_token, 'Access token must not be nil'

# --- Step 4: Introspection ---
introspection_request = Authlete::Models::Components::IntrospectionRequest.new(
token: access_token
)
response = @authlete_client.introspection.process_request(
service_id: @service_id,
introspection_request: introspection_request
)

intro_resp = response.introspection_response
assert_equal 'OK', intro_resp.action.serialize,
"Expected OK action for introspection, got #{intro_resp.action}: #{intro_resp.result_message}"

# --- Step 5: Revocation ---
revocation_request = Authlete::Models::Components::RevocationRequest.new(
parameters: "token=#{access_token}",
client_id: @client_id,
client_secret: @client_secret
)
response = @authlete_client.revocation.process_request(
service_id: @service_id,
revocation_request: revocation_request
)

revocation_resp = response.revocation_response
assert_equal 'OK', revocation_resp.action.serialize,
"Expected OK action for revocation, got #{revocation_resp.action}"
end
end
Loading
Loading