Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
85a76d0
test: add authorization code flow
shaq-authlete Mar 13, 2026
c1f8176
test: pkce flow
shaq-authlete Mar 13, 2026
b4fb0f4
test: par
shaq-authlete Mar 13, 2026
19c7f88
test: dpop
shaq-authlete Mar 14, 2026
27acd96
test: refresh tokens
shaq-authlete Mar 14, 2026
62b196f
test: openid basic flow
shaq-authlete Mar 15, 2026
5c425b5
test: openid pkce
shaq-authlete Mar 15, 2026
469b87d
test: openid par
shaq-authlete Mar 15, 2026
45cc293
test: openid dpop
shaq-authlete Mar 15, 2026
d857d98
chore: rename folders
shaq-authlete Mar 15, 2026
431177b
chore: use service access token for tests instead of org token
shaq-authlete Mar 15, 2026
13ffc52
chore: wip use service update instead of create
shaq-authlete Mar 15, 2026
a9eddf3
chore: finish refactor non-openid tests
shaq-authlete Mar 15, 2026
746e494
chore: store token duration in variable
shaq-authlete Mar 15, 2026
7b7a365
fix: add back failing test
shaq-authlete Mar 15, 2026
f1defdc
fix: add introspect helper to multiple tests
shaq-authlete Mar 15, 2026
678eddd
docs: update readme
shaq-authlete Mar 16, 2026
30b49b5
fix: use org token for service and client management
shaq-authlete Mar 16, 2026
f3b3a25
chore: update rakefile comments
shaq-authlete Mar 16, 2026
c87ad1a
feat: extra properties failing test
shaq-authlete Mar 19, 2026
da666e1
chore: simplify payload creatin
shaq-authlete Mar 19, 2026
2cc5306
chore: use conventions used in readme
shaq-authlete Mar 26, 2026
37e90a7
ci: run integration test on PR and main
shaq-authlete Mar 26, 2026
7f4a5d9
fix: undo Rakefile changes
shaq-authlete Mar 30, 2026
034d122
docs: update test readme with local instructions
shaq-authlete Mar 30, 2026
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