Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
trasher committed Jan 28, 2024
1 parent 4c86816 commit e60f286
Show file tree
Hide file tree
Showing 8 changed files with 531 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
vendor/
.phpunit.result.cache
.idea/
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 Galette Community
Copyright (©) 2024 The Galette Team

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Galette Provider for OAuth 2.0 Client

This package provides Galette OAuth 2.0 support for the PHP League's [OAuth 2.0 Client](https://github.com/thephpleague/oauth2-client).

The [Galette OAuth plugin](https://galette-community.github.io/plugin-oauth2/) must be installed on you [Galette](https://galette.eu) instance.

## Installation

```cmd
composer require galette-community/oauth2-galette
```

## Usage

```php
$galetteProvider = new \Galette\OAuth2\Client\Provider\Galette([
//information related to the app where you will use galette-oauth2
'clientId' => 'yourId', // The client ID assigned to you
'clientSecret' => 'yourSecret', // The client password assigned to you
'redirectUri' => 'yourRedirectUri', // The return URL you specified for your app
//information related to the galette instance you want to connect to
'instance' => 'yourInstance', // The instance of Galette you want to connect to
'pluginDir' => 'yourPluginDir', // The directory where the plugin is installed - defaults to 'plugin-oauth2'
]);

// Get authorization code
if (!isset($_GET['code'])) {
// Options are optional, defaults to 'read_prefs' only
$options = ['instance' => 'https://my.galette'];

// Get authorization URL
$authorizationUrl = $galetteProvider->getAuthorizationUrl($options);

// Get state and store it to the session
$_SESSION['oauth2state'] = $galetteProvider->getState();

// Redirect user to authorization URL
header('Location: ' . $authorizationUrl);
exit;
// Check for errors
} elseif (empty($_GET['state']) || (isset($_SESSION['oauth2state']) && $_GET['state'] !== $_SESSION['oauth2state'])) {
if (isset($_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
}
exit('Invalid state');
} else {
// Get access token
try {
$accessToken = $galetteProvider->getAccessToken(
'authorization_code',
[
'code' => $_GET['code']
]
);
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
exit($e->getMessage());
}

// Get resource owner
try {
$resourceOwner = $galetteProvider->getResourceOwner($accessToken);
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
exit($e->getMessage());
}

// Now you can store the results to session etc.
$_SESSION['accessToken'] = $accessToken;
$_SESSION['resourceOwner'] = $resourceOwner;

var_dump(
$resourceOwner->getId(),
$resourceOwner->getEmail(),
$resourceOwner->getUsername(),
$resourceOwner->getLang(),
$resourceOwner->getStatus(),
$resourceOwner->toArray()
);
}
```

For more information see the PHP League's general usage examples.

## Testing

``` bash
./vendor/bin/phpunit
```

## License

The MIT License (MIT). Please see [License File](https://github.com/jbelien/oauth2-openstreetmap/blob/master/LICENSE) for more information.
38 changes: 38 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "galette/oauth2-galette",
"description": "Galette OAuth 2.0 support for the PHP League's OAuth 2.0 client",
"license": "MIT",
"authors": [
{
"name": "Johan Cwiklinski",
"homepage": "https://github.com/trashy"
}
],
"keywords": [
"oauth",
"oauth2",
"client",
"authorization",
"authorisation",
"galette"
],
"require": {
"php": "^8.1",
"league/oauth2-client": "^2.7"
},
"autoload": {
"psr-4": {
"Galette\\OAuth2\\Client\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Galette\\OAuth2\\Client\\Test\\": "tests/src/"
}
},
"require-dev": {
"phpunit/phpunit": "^10.5",
"squizlabs/php_codesniffer": "^3.8",
"mockery/mockery": "^1.6"
}
}
13 changes: 13 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
bootstrap="vendor/autoload.php"
colors="true"
processIsolation="false"
stopOnFailure="false"
>
<testsuites>
<testsuite name="Package Test Suite">
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
101 changes: 101 additions & 0 deletions src/Provider/Galette.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types=1);

namespace Galette\OAuth2\Client\Provider;

use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
use Psr\Http\Message\ResponseInterface;

class Galette extends AbstractProvider
{
use BearerAuthorizationTrait;

/**
* Galette instance URL
*
* @var string
*/
protected string $instance;

/**
* Plugin installation directory
*
* @var string
*/
protected string $pluginDirectory = 'plugin-oauth2';

/**
* @var array
*/
protected array $scope;

public function __construct(array $options = [], array $collaborators = [])
{
if (!isset($options['instance'])) {
throw new \InvalidArgumentException(
'The "instance" option not set. Please set a Galette instance URL.'
);
}
$this->instance = $options['instance'];

if (isset($options['scope'])) {
$this->scope = $options['scope'];
}

if (isset($options['pluginDir'])) {
$this->pluginDirectory = $options['pluginDir'];
}

parent::__construct($options, $collaborators);
}

public function getBaseURL(): string
{
return sprintf(
'%s/plugins/%s',
trim($this->instance, '/'),
$this->pluginDirectory
);
}

public function getBaseAuthorizationUrl()
{
return $this->getBaseURL() . '/authorize';
}

public function getBaseAccessTokenUrl(array $params)
{
return $this->getBaseURL() . '/access_token';
}

public function getResourceOwnerDetailsUrl(AccessToken $token)
{
return $this->getBaseURL() . '/user';
}

protected function getDefaultScopes()
{
return [];
}

protected function checkResponse(ResponseInterface $response, $data)
{
$statusCode = $response->getStatusCode();
if ($statusCode > 400) {
throw new IdentityProviderException(
$data['message'] ?: $response->getReasonPhrase(),
$statusCode,
$response
);
}
}

protected function createResourceOwner(array $response, AccessToken $token)
{
return new GaletteResourceOwner($response);
}
}
82 changes: 82 additions & 0 deletions src/Provider/GaletteResourceOwner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Galette\OAuth2\Client\Provider;

use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Tool\ArrayAccessorTrait;

class GaletteResourceOwner implements ResourceOwnerInterface
{
use ArrayAccessorTrait;

/**
* @var array<string, mixed>
*/
protected array $response;

public function __construct(array $response = [])
{
$this->response = $response;
}

/**
* Get resource owner id
*
* @return int|null
*/
public function getId(): ?int
{
return $this->getValueByKey($this->response, 'id');
}

/**
* Get resource owner email
*
* @return string|null
*/
public function getEmail(): ?string
{
return $this->getValueByKey($this->response, 'email');
}

/**
* Get resource owner username
*
* @return string|null
*/
public function getUsername(): ?string
{
return $this->getValueByKey($this->response, 'username');
}

/**
* Get resource owner language
*
* @return string|null
*/
public function getLang(): ?string
{
return $this->getValueByKey($this->response, 'language');
}

/**
* Get resource owner membership status
*
* @return int|null
*/
public function getStatus(): ?int
{
return (int)$this->getValueByKey($this->response, 'status');
}


/**
* Return all owner details available as an array.
*
* @return array
*/
public function toArray(): array
{
return $this->response;
}
}
Loading

0 comments on commit e60f286

Please sign in to comment.