mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
chore(console): align PHP/Python guide structure with docs (#5420)
This commit is contained in:
parent
605ef09ed0
commit
ee036bd77d
3 changed files with 75 additions and 128 deletions
|
@ -104,40 +104,6 @@ Route::get('/callback', function () {
|
|||
|
||||
</Step>
|
||||
|
||||
<Step title="Implement the home page">
|
||||
|
||||
Here we implement a simple home page for demonstration:
|
||||
|
||||
- If the user is not signed in, show a sign-in button;
|
||||
- If the user is signed in, show some basic information about the user.
|
||||
|
||||
```php
|
||||
Route::get('/', function () {
|
||||
if ($client->isAuthenticated() === false) {
|
||||
return "Not authenticated <a href='/sign-in'>Sign in</a>";
|
||||
}
|
||||
|
||||
return (
|
||||
// Get local ID token claims
|
||||
$client->getIdTokenClaims()->modelDumpJson(excludeUnset: true)
|
||||
. "<br>"
|
||||
// Fetch user info from Logto userinfo endpoint
|
||||
$client->fetchUserInfo()->modelDumpJson(excludeUnset: true)
|
||||
. "<br><a href='/sign-out'>Sign out</a>"
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
Our data models are based on [JsonModel](https://github.com/logto-io/php/blob/HEAD/docs/api/classes/Logto/Sdk/Models/JsonModel.md), which is safe to accept undefined keys while encoding or decoding JSON.
|
||||
|
||||
Note that a field (claim) with `null` value doesn't mean the field is set. The reason may be the related scope is not requested, or the user doesn't have the field.
|
||||
|
||||
For example, if we didn't request the `email` scope when signing in, and the `email` field will be `null`. However, if we requested the `email` scope, the `email` field will be the user's email address if available.
|
||||
|
||||
To learn more about scopes and claims, see [Scopes and claims](https://github.com/logto-io/php/blob/HEAD/docs/tutorial.md#scopes-and-claims).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Implement the sign-out route">
|
||||
|
||||
To clean up the Python session and Logto session, we can designate a post sign-out redierct URI. This is where Logto will redirect users after they sign out.
|
||||
|
@ -161,6 +127,42 @@ The post sign-out redierct URI is optional, and if not provided, the user will b
|
|||
|
||||
</Step>
|
||||
|
||||
<Step title="Handle authentication status">
|
||||
|
||||
In Logto SDK, we can use `$client->isAuthenticated()` to check the authentication status, if the user is signed in, the value will be true, otherwise, the value will be false.
|
||||
|
||||
We also need to implement a home page for demonstration:
|
||||
|
||||
- If the user is not signed in, show a sign-in button;
|
||||
- If the user is signed in, show some basic information about the user.
|
||||
|
||||
```php
|
||||
Route::get('/', function () {
|
||||
if ($client->isAuthenticated() === false) {
|
||||
return "Not authenticated <a href='/sign-in'>Sign in</a>";
|
||||
}
|
||||
|
||||
return (
|
||||
// Get local ID token claims
|
||||
json_decode($client->getIdTokenClaims())
|
||||
. "<br>"
|
||||
// Fetch user info from Logto userinfo endpoint
|
||||
json_decode($client->fetchUserInfo())
|
||||
. "<br><a href='/sign-out'>Sign out</a>"
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
Our data models are based on [JsonModel](https://github.com/logto-io/php/blob/master/docs/api/classes/Logto/Sdk/Models/JsonModel.md), which is safe to accept undefined keys while encoding or decoding JSON.
|
||||
|
||||
Note that a field (claim) with `null` value doesn't mean the field is set. The reason may be the related scope is not requested, or the user doesn't have the field.
|
||||
|
||||
For example, if we didn't request the `email` scope when signing in, and the `email` field will be `null`. However, if we requested the `email` scope, the `email` field will be the user's email address if available.
|
||||
|
||||
To learn more about scopes and claims, see [Get user information](https://docs.logto.io/sdk/php/#get-user-information).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Checkpoint: Test your application">
|
||||
|
||||
Now, you can test your application:
|
||||
|
@ -174,35 +176,4 @@ Now, you can test your application:
|
|||
|
||||
</Step>
|
||||
|
||||
<Step title="Protect your routes">
|
||||
|
||||
Now, you have a working sign-in flow, but your routes are still unprotected. Per the framework you use, you can create a middleware to protect your routes. For example, in Laravel, you can create a middleware as follows:
|
||||
|
||||
```php
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class LogtoAuth
|
||||
{
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if ($client->isAuthenticated() === false) {
|
||||
return redirect('/sign-in');
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, you can apply this middleware to your routes:
|
||||
|
||||
```php
|
||||
Route::get('/protected', function () {
|
||||
return "Protected page";
|
||||
})->middleware(LogtoAuth::class);
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
|
|
@ -6,6 +6,10 @@ const metadata: Readonly<GuideMetadata> = Object.freeze({
|
|||
name: 'PHP',
|
||||
description: 'Integrate Logto into your PHP web app, such as Lavarel.',
|
||||
target: ApplicationType.Traditional,
|
||||
sample: {
|
||||
repo: 'php',
|
||||
path: 'samples',
|
||||
},
|
||||
fullTutorial: {
|
||||
title: 'Full PHP SDK tutorial',
|
||||
url: 'https://docs.logto.io/sdk/php',
|
||||
|
|
|
@ -120,39 +120,6 @@ async def callback():
|
|||
|
||||
</Step>
|
||||
|
||||
<Step title="Implement the home page">
|
||||
|
||||
Here we implement a simple home page for demonstration:
|
||||
|
||||
- If the user is not signed in, show a sign-in button;
|
||||
- If the user is signed in, show some basic information about the user.
|
||||
|
||||
```python
|
||||
@app.route("/")
|
||||
async def home():
|
||||
if client.isAuthenticated() is False:
|
||||
return "Not authenticated <a href='/sign-in'>Sign in</a>"
|
||||
|
||||
return (
|
||||
# Get local ID token claims
|
||||
client.getIdTokenClaims().model_dump_json(exclude_unset=True)
|
||||
+ "<br>"
|
||||
# Fetch user info from Logto userinfo endpoint
|
||||
(await client.fetchUserInfo()).model_dump_json(exclude_unset=True)
|
||||
+ "<br><a href='/sign-out'>Sign out</a>"
|
||||
)
|
||||
```
|
||||
|
||||
Our data models are based on [pydantic](https://docs.pydantic.dev/), so you can use `model_dump_json` to dump the data model to JSON.
|
||||
|
||||
Adding `exclude_unset=True` will exclude unset fields from the JSON output, which makes the output more precise.
|
||||
|
||||
For example, if we didn't request the `email` scope when signing in, and the `email` field will be excluded from the JSON output. However, if we requested the `email` scope, but the user doesn't have an email address, the `email` field will be included in the JSON output with a `null` value.
|
||||
|
||||
To learn more about scopes and claims, see [Scopes and claims](https://github.com/logto-io/python/blob/HEAD/docs/tutorial.md#scopes-and-claims).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Implement the sign-out route">
|
||||
|
||||
To clean up the Python session and Logto session, we can designate a post sign-out redierct URI. This is where Logto will redirect users after they sign out.
|
||||
|
@ -179,6 +146,41 @@ async def sign_out():
|
|||
|
||||
</Step>
|
||||
|
||||
<Step title="Handle authentication status">
|
||||
|
||||
In Logto SDK, we can use `client.isAuthenticated()` to check the authentication status, if the user is signed in, the value will be true, otherwise, the value will be false.
|
||||
|
||||
Here we also implement a simple home page for demonstration:
|
||||
|
||||
- If the user is not signed in, show a sign-in button;
|
||||
- If the user is signed in, show some basic information about the user.
|
||||
|
||||
```python
|
||||
@app.route("/")
|
||||
async def home():
|
||||
if client.isAuthenticated() is False:
|
||||
return "Not authenticated <a href='/sign-in'>Sign in</a>"
|
||||
|
||||
return (
|
||||
# Get local ID token claims
|
||||
client.getIdTokenClaims().model_dump_json(exclude_unset=True)
|
||||
+ "<br>"
|
||||
# Fetch user info from Logto userinfo endpoint
|
||||
(await client.fetchUserInfo()).model_dump_json(exclude_unset=True)
|
||||
+ "<br><a href='/sign-out'>Sign out</a>"
|
||||
)
|
||||
```
|
||||
|
||||
Our data models are based on [pydantic](https://docs.pydantic.dev/), so you can use `model_dump_json` to dump the data model to JSON.
|
||||
|
||||
Adding `exclude_unset=True` will exclude unset fields from the JSON output, which makes the output more precise.
|
||||
|
||||
For example, if we didn't request the `email` scope when signing in, and the `email` field will be excluded from the JSON output. However, if we requested the `email` scope, but the user doesn't have an email address, the `email` field will be included in the JSON output with a `null` value.
|
||||
|
||||
To learn more about scopes and claims, see [Get user information](https://docs.logto.io/sdk/python/#get-user-information).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Checkpoint: Test your application">
|
||||
|
||||
Now, you can test your application:
|
||||
|
@ -192,34 +194,4 @@ Now, you can test your application:
|
|||
|
||||
</Step>
|
||||
|
||||
<Step title="Protect your routes">
|
||||
|
||||
Now, you have a working sign-in flow, but your routes are still unprotected. Per the framework you use, you can create a decorator such as `@authenticated` to protect your routes. For example:
|
||||
|
||||
```python
|
||||
from functools import wraps
|
||||
|
||||
def authenticated(func):
|
||||
@wraps(func)
|
||||
async def wrapper(*args, **kwargs):
|
||||
if client.isAuthenticated() is False:
|
||||
return redirect("/sign-in") # Or directly call `client.signIn`
|
||||
return await func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
```
|
||||
|
||||
Then, you can use the decorator to protect your routes:
|
||||
|
||||
```python
|
||||
@app.route("/protected")
|
||||
@authenticated
|
||||
async def protected():
|
||||
return "Protected page"
|
||||
```
|
||||
|
||||
You can also create a middleware to achieve the same goal.
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
|
Loading…
Reference in a new issue