Skip to content

Commit

Permalink
feat: support organizations (#6)
Browse files Browse the repository at this point in the history
* feat: support organizations

* chore: add organization doc link

* chore: update docs
  • Loading branch information
gao-sun authored Nov 29, 2023
1 parent a58a8dc commit c7cf241
Show file tree
Hide file tree
Showing 20 changed files with 434 additions and 43 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
}
},
"scripts": {
"dev": "php -S localhost:5000 samples/index.php",
"dev": ["Composer\\Config::disableProcessTimeout", "php -S localhost:5000 -t samples"],
"test": "phpunit tests",
"docs": "rm -rf docs/api && php phpDocumentor.phar && prettier --write docs/api"
},
Expand Down
36 changes: 36 additions & 0 deletions docs/api/classes/Logto/Sdk/LogtoClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,24 @@ public getAccessToken(string $resource = ''): ?string

---

### getOrganizationToken

Get the access token for the given organization ID. If the access token is
expired, it will be refreshed automatically. If no refresh token is found,
null will be returned.

```php
public getOrganizationToken(string $organizationId): ?string
```

**Parameters:**

| Parameter | Type | Description |
| ----------------- | ---------- | ----------- |
| `$organizationId` | **string** | |

---

### getAccessTokenClaims

Get the claims in the access token for the given resource. If the access token
Expand All @@ -118,6 +136,24 @@ public getAccessTokenClaims(string $resource = ''): \Logto\Sdk\Models\

---

### getOrganizationTokenClaims

Get the claims in the access token for the given organization ID. If the access
token is expired, it will be refreshed automatically. If it's unable to refresh
the access token, an exception will be thrown.

```php
public getOrganizationTokenClaims(string $organizationId): \Logto\Sdk\Models\AccessTokenClaims
```

**Parameters:**

| Parameter | Type | Description |
| ----------------- | ---------- | ----------- |
| `$organizationId` | **string** | |

---

### getRefreshToken

Get the refresh token string.
Expand Down
14 changes: 14 additions & 0 deletions docs/api/classes/Logto/Sdk/LogtoConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ public __construct(string $endpoint, string $appId, ?string $appSecret = null, ?

---

### hasOrganizationScope

Check if the organization scope is requested by the configuration.

```php
public hasOrganizationScope(): bool
```

**See Also:**

- \Logto\Sdk\Constants\UserScope::organizations -

---

---

> Automatically generated from source code comments using [phpDocumentor](http://www.phpdoc.org/) and [saggre/phpdocumentor-markdown](https://github.com/Saggre/phpDocumentor-markdown)
35 changes: 34 additions & 1 deletion docs/api/classes/Logto/Sdk/Models/IdTokenClaims.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,42 @@ public ?bool $phone_number_verified

---

### roles

The user's roles.

```php
public ?array $roles
```

---

### organizations

The user's organization IDs.

```php
public ?array $organizations
```

---

### organization_roles

The user's organization roles.

```php
public ?array $organization_roles
```

---

## Methods

### \_\_construct

```php
public __construct(string $iss, string $sub, string $aud, int $exp, int $iat, ?string $at_hash = null, ?string $name = null, ?string $username = null, ?string $picture = null, ?string $email = null, ?bool $email_verified = null, ?string $phone_number = null, ?bool $phone_number_verified = null, mixed $extra): mixed
public __construct(string $iss, string $sub, string $aud, int $exp, int $iat, ?string $at_hash = null, ?string $name = null, ?string $username = null, ?string $picture = null, ?string $email = null, ?bool $email_verified = null, ?string $phone_number = null, ?bool $phone_number_verified = null, ?array $roles = null, ?array $organizations = null, ?array $organization_roles = null, mixed $extra): mixed
```

**Parameters:**
Expand All @@ -162,6 +192,9 @@ public __construct(string $iss, string $sub, string $aud, int $exp, int $iat, ?s
| `$email_verified` | **?bool** | |
| `$phone_number` | **?string** | |
| `$phone_number_verified` | **?bool** | |
| `$roles` | **?array** | |
| `$organizations` | **?array** | |
| `$organization_roles` | **?array** | |
| `$extra` | **mixed** | |

---
Expand Down
35 changes: 32 additions & 3 deletions docs/api/classes/Logto/Sdk/Oidc/OidcCore.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ instance methods.

## Constants

| Constant | Visibility | Type | Value |
| :--------------- | :--------- | :--- | :-------------------------------------------------------------------- |
| `DEFAULT_SCOPES` | public | | ['openid', 'offline_access', 'profile'] |
| Constant | Visibility | Type | Value |
| :------------------------ | :--------- | :--- | :--------------------------------------------------------------------------------------------------------------------------------------- |
| `DEFAULT_SCOPES` | public | | [\Logto\Sdk\Constants\ReservedScope::openId, \Logto\Sdk\Constants\ReservedScope::offlineAccess, \Logto\Sdk\Constants\UserScope::profile] |
| `ORGANIZATION_URN_PREFIX` | public | | 'urn:logto:organization:' |

## Properties

Expand Down Expand Up @@ -109,6 +110,31 @@ See [Client Creates the Code Challenge](https://www.rfc-editor.org/rfc/rfc7636.h

---

### buildOrganizationUrn

Build the organization URN for the given organization ID.

```php
public static buildOrganizationUrn(string $organizationId): string
```

For example, if the organization ID is `123`, the organization URN will be
`urn:logto:organization:123`.

- This method is **static**.

**Parameters:**

| Parameter | Type | Description |
| ----------------- | ---------- | ----------- |
| `$organizationId` | **string** | |

**See Also:**

- - [RFC 0001](https://github.com/logto-io/rfcs) to learn more.

---

### \_\_construct

Initialize the OIDC core with the provider metadata. You can use the
Expand Down Expand Up @@ -177,6 +203,9 @@ Fetch the token for the given resource from the token endpoint using the refresh
public fetchTokenByRefreshToken(string $clientId, ?string $clientSecret, string $refreshToken, string $resource = ''): \Logto\Sdk\Oidc\TokenResponse
```

If the resource is an organization URN, the organization ID will be extracted from
the URN and the `organization_id` parameter will be sent to the token endpoint.

**Parameters:**

| Parameter | Type | Description |
Expand Down
35 changes: 34 additions & 1 deletion docs/api/classes/Logto/Sdk/Oidc/UserInfoResponse.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,36 @@ public ?bool $phone_number_verified

---

### roles

The user's roles.

```php
public ?array $roles
```

---

### organizations

The user's organization IDs.

```php
public ?array $organizations
```

---

### organization_roles

The user's organization roles.

```php
public ?array $organization_roles
```

---

### custom_data

The custom data of the user, can be any JSON object.
Expand All @@ -115,7 +145,7 @@ public ?array $identities
### \_\_construct

```php
public __construct(string $sub, ?string $name = null, ?string $username = null, ?string $picture = null, ?string $email = null, ?bool $email_verified = null, ?string $phone_number = null, ?bool $phone_number_verified = null, mixed $custom_data = null, ?array $identities = null, mixed $extra): mixed
public __construct(string $sub, ?string $name = null, ?string $username = null, ?string $picture = null, ?string $email = null, ?bool $email_verified = null, ?string $phone_number = null, ?bool $phone_number_verified = null, ?array $roles = null, ?array $organizations = null, ?array $organization_roles = null, mixed $custom_data = null, ?array $identities = null, mixed $extra): mixed
```

**Parameters:**
Expand All @@ -130,6 +160,9 @@ public __construct(string $sub, ?string $name = null, ?string $username = null,
| `$email_verified` | **?bool** | |
| `$phone_number` | **?string** | |
| `$phone_number_verified` | **?bool** | |
| `$roles` | **?array** | |
| `$organizations` | **?array** | |
| `$organization_roles` | **?array** | |
| `$custom_data` | **mixed** | |
| `$identities` | **?array** | |
| `$extra` | **mixed** | |
Expand Down
2 changes: 2 additions & 0 deletions docs/api/classes/Logto/Sdk/Storage/Storage.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
---

# Storage

The storage interface for the Logto client. Logto client will use this
Expand Down
2 changes: 2 additions & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
---

# Logto PHP SDK

This is an automatically generated documentation for **Logto PHP SDK**.
Expand Down
74 changes: 57 additions & 17 deletions docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ This tutorial will show you how to integrate Logto into your PHP web application

## Table of contents

- [Logto PHP SDK tutorial](#logto-php-sdk-tutorial)
- [Table of contents](#table-of-contents)
- [Installation](#installation)
- [Integration](#integration)
- [Init LogtoClient](#init-logtoclient)
- [Implement the sign-in route](#implement-the-sign-in-route)
- [Implement the callback route](#implement-the-callback-route)
- [Implement the home page](#implement-the-home-page)
- [Implement the sign-out route](#implement-the-sign-out-route)
- [Checkpoint: Test your application](#checkpoint-test-your-application)
- [Protect your routes](#protect-your-routes)
- [Scopes and claims](#scopes-and-claims)
- [Special ID token claims](#special-id-token-claims)
- [API resources](#api-resources)
- [Configure Logto client](#configure-logto-client)
- [Fetch access token for the API resource](#fetch-access-token-for-the-api-resource)
- [Table of contents](#table-of-contents)
- [Installation](#installation)
- [Integration](#integration)
- [Init LogtoClient](#init-logtoclient)
- [Implement the sign-in route](#implement-the-sign-in-route)
- [Implement the callback route](#implement-the-callback-route)
- [Implement the home page](#implement-the-home-page)
- [Implement the sign-out route](#implement-the-sign-out-route)
- [Checkpoint: Test your application](#checkpoint-test-your-application)
- [Protect your routes](#protect-your-routes)
- [Scopes and claims](#scopes-and-claims)
- [Special ID token claims](#special-id-token-claims)
- [API resources](#api-resources)
- [Configure Logto client](#configure-logto-client)
- [Fetch access token for the API resource](#fetch-access-token-for-the-api-resource)
- [Fetch organization token for user](#fetch-organization-token-for-user)

## Installation

Expand Down Expand Up @@ -200,7 +200,20 @@ By default, Logto SDK requests three scopes: `openid`, `profile`, and `offline_a
$client = new LogtoClient(
new LogtoConfig(
// ...other configs
scopes: ["email", "phone"], // Add more scopes
scopes: ["email", "phone"], // Update per your needs
),
);
```

Alternatively, you can use the `UserScope` enum to add scopes:

```php
use Logto\Sdk\Constants\UserScope;

$client = new LogtoClient(
new LogtoConfig(
// ...other configs
scopes: [UserScope::email, UserScope::phone], // Update per your needs
),
);
```
Expand Down Expand Up @@ -280,3 +293,30 @@ $accessToken = $client->getAccessToken("https://shopping.your-app.com/api");
This method will return a JWT access token that can be used to access the API resource, if the user has the proper permissions. If the current cached access token has expired, this method will automatically try to use the refresh token to get a new access token.

If failed by any reason, this method will return `null`.

### Fetch organization token for user

If organization is new to you, please read [🏢 Organizations (Multi-tenancy)](https://docs.logto.io/docs/recipes/organizations/) to get started.

You need to add `UserScope.organizations` scope when configuring the Logto client:

```php
use Logto\Sdk\Constants\UserScope;

$client = new LogtoClient(
new LogtoConfig(
// ...other configs
scopes: [UserScope::organizations], // Add scopes
),
);
```

Once the user is signed in, you can fetch the organization token for the user:

```php
# Replace the parameter with a valid organization ID.
# Valid organization IDs for the user can be found in the ID token claim `organizations`.
$organizationToken = $client->getOrganizationToken("organization-id");
# or
$claims = $client->getOrganizationTokenClaims("organization-id");
```
Loading

0 comments on commit c7cf241

Please sign in to comment.