Skip to content
Merged
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
59 changes: 59 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: "CI"

on: [pull_request]

jobs:
codeql:
name: CodeQL
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 2

- run: git checkout HEAD^2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 CI tests unmerged branch, not the merge result

git checkout HEAD^2 resets every job to the PR branch tip rather than the merge commit that GitHub Actions checks out by default. This means integration breakage — e.g., a conflict resolution in the merge commit, or a breaking change on main that landed between branch creation and merge — goes untested. CI can report green while the actual merged code fails to build or passes tests with different behaviour. The same step is present in all three jobs (codeql, linter, tests). Removing these three git checkout HEAD^2 steps restores the standard behaviour of validating the merged result.


- name: Run CodeQL
run: |
docker run --rm -v $PWD:/app composer:2.6 sh -c \
"composer install --profile --ignore-platform-reqs && composer check"

linter:
name: Linter
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 2

- run: git checkout HEAD^2

- name: Run Linter
run: |
docker run --rm -v $PWD:/app composer sh -c \
"composer install --profile --ignore-platform-reqs && composer lint"

tests:
name: Tests
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
fetch-depth: 2

- run: git checkout HEAD^2

- name: Build
run: |
docker compose build
docker compose up -d
sleep 10

- name: Run Tests
run: docker compose exec tests vendor/bin/phpunit --configuration phpunit.xml tests
20 changes: 0 additions & 20 deletions .github/workflows/code-ql-analysis.yml

This file was deleted.

20 changes: 0 additions & 20 deletions .github/workflows/linter.yml

This file was deleted.

24 changes: 0 additions & 24 deletions .github/workflows/tests.yml

This file was deleted.

36 changes: 32 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,22 @@ $accessToken = new AccessToken(
// Issue a signed RS256 access token
$jwt = $accessToken->issue(
subject: 'user-123', // "sub" — the resource owner
audience: 'https://api.example.com', // "aud" — the resource server
audience: ['https://api.example.com'], // "aud" — the resource server
clientId: 'client-abc', // "client_id" — the client it was issued to
authTime: time(), // "auth_time" — when the user authenticated
duration: 3600, // Lifetime in seconds ("exp")
scopes: ['openid', 'profile', 'email']
);

$jwt = $accessToken->issue(
subject: 'user-123',
audience: ['https://api.example.com', 'https://mcp.example.com'],
clientId: 'client-abc',
authTime: time(),
duration: 3600,
scopes: ['openid', 'profile']
);

// Publish the public key as a JWK so resource servers can verify tokens
$jwk = $accessToken->getPublicJwk();
$keyId = $accessToken->getKeyId();
Expand Down Expand Up @@ -256,6 +265,25 @@ $jwt = $idToken->issue(

> Both asymmetric and symmetric issuers accept an optional `keyId` constructor argument (the JWS `kid` header) for key rotation. For asymmetric issuers it is derived deterministically from the public key when omitted.

#### OAuth2 Resource Indicators (RFC 8707)

```php
<?php

use Utopia\Auth\OAuth2\ResourceIndicators;

$resources = ResourceIndicators::from([
'https://api.example.com/',
'https://mcp.example.com/',
]);
$previouslyGrantedResources = ResourceIndicators::from(['https://api.example.com/']);

$isAllowed = $resources->isSubsetOf($previouslyGrantedResources);
$unchanged = $resources->equals($previouslyGrantedResources);
$audience = $resources->audience('https://cloud.example.com/v1/project');
$serialized = $resources->toArray();
```

## Tests

To run all unit tests, use the following Docker command:
Expand All @@ -264,10 +292,10 @@ To run all unit tests, use the following Docker command:
docker compose exec tests vendor/bin/phpunit --configuration phpunit.xml tests
```

To run static code analysis, use the following Psalm command:
To run static code analysis, use the following command:

```bash
docker compose exec tests vendor/bin/psalm --show-info=true
docker compose exec tests composer check
```

## Security
Expand All @@ -282,4 +310,4 @@ We truly ❤️ pull requests! If you wish to help, you can learn more about how

## Copyright and license

The MIT License (MIT) [http://www.opensource.org/licenses/mit-license.php](http://www.opensource.org/licenses/mit-license.php)
The MIT License (MIT) [http://www.opensource.org/licenses/mit-license.php](http://www.opensource.org/licenses/mit-license.php)
9 changes: 4 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
}
},
"scripts": {
"check": "./vendor/bin/phpstan analyse --level max src tests",
"check": "./vendor/bin/phpstan analyse --level max --memory-limit=1G src tests",
"lint": "./vendor/bin/pint --config pint.json --test",
"format": "./vendor/bin/pint --config pint.json"
},
Expand All @@ -35,8 +35,7 @@
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"vimeo/psalm": "4.0.1",
"laravel/pint": "1.2.*",
"phpstan/phpstan": "1.9.x-dev"
"laravel/pint": "^1.29",
"phpstan/phpstan": "^1.12"
}
}
}
Loading
Loading