diff --git a/docs/Development/Using-examples.md b/docs/Development/Using-examples.md
deleted file mode 100644
index 25333d2..0000000
--- a/docs/Development/Using-examples.md
+++ /dev/null
@@ -1 +0,0 @@
-# Using the examples
diff --git a/docs/Readme.md b/docs/Readme.md
index 6879a79..cc51cd6 100644
--- a/docs/Readme.md
+++ b/docs/Readme.md
@@ -66,6 +66,7 @@ The markdown sources for the [Read the Docs online manual](https://php-oauth.rea
- [Quickstart](./Usage/Quickstart.md)
- [Authorization flow](./Usage/Authorization.md)
+- [Using the examples](./Usage/Using-examples.md)
### Development
@@ -73,7 +74,6 @@ The markdown sources for the [Read the Docs online manual](https://php-oauth.rea
- [Create a Provider](./Development/Create-provider.md)
- [Additional functionality](./Development/Additional-functionality.md)
- [Running tests](./Development/Test-suite.md)
-- [Using the examples](./Development/Using-examples.md)
### Appendix
diff --git a/docs/Usage/Authorization.md b/docs/Usage/Authorization.md
index 3bac4bd..053e5f7 100644
--- a/docs/Usage/Authorization.md
+++ b/docs/Usage/Authorization.md
@@ -20,7 +20,7 @@ echo 'connect with GitHub!';
The method `OAuthInterface::getAuthorizationURL()` takes two (optional) parameters:
-- `$params`: this array contains additional query parameters that will be added to the URL query (provider dependent)
+- `$params`: this array contains additional query parameters that will be added to the URL query (service dependent)
- `$scopes`: this array contains all scopes that will be used for this authorization
When the user clicks the log-in link, just execute a `header()` to the provider's authorization URL.
@@ -30,7 +30,7 @@ if($route === 'oauth-login'){
header('Location: '.$provider->getAuthorizationURL($params, $scopes));
// -> https://github.com/login/oauth/authorize?client_id=
- // &redirect_uri=https%3A%2F%2Fexample.com%2Fcallback%2F&response_type=code
+ // &redirect_uri=https%3A%2F%2Fexample.com%2Foauth%2F&response_type=code
// &scope=&state=&type=web_server
}
```
@@ -47,7 +47,7 @@ while the similar `OAuth2Interface::getAccessToken()` takes two parameters `$cod
### OAuth2
-In our GitHub OAuth2 example we're now receiving the incoming callback to `https://example.com/callback/?code=&state=`.
+In our GitHub OAuth2 example we're now receiving the incoming callback to `https://example.com/oauth/?code=&state=`.
The `getAccessToken()` method initiates a backend request to the provider's server to exchange the temporary credentials for an access token:
```php
diff --git a/docs/Usage/Quickstart.md b/docs/Usage/Quickstart.md
index 2f153c2..eec33ed 100644
--- a/docs/Usage/Quickstart.md
+++ b/docs/Usage/Quickstart.md
@@ -40,6 +40,7 @@ $options->sessionStart = true;
$storage = new SessionStorage($options);
```
+
### Using existing tokens
Most of the time you'll probably just want to use/import an existing access token to use an API on the user's behalf.
@@ -79,11 +80,36 @@ $provider->storeAccessToken($token);
To invoke an OAuth provider, you'll need a `OAuthOptions` instance, a [PSR-18](https://www.php-fig.org/psr/psr-18/) `ClientInterface` (such as [`guzzlehttp/guzzle`](https://github.com/guzzle/guzzle) or [`chillerlan/php-httpinterface`](https://github.com/chillerlan/php-httpinterface)),
along with the [PSR-17](https://www.php-fig.org/psr/psr-17/) factories `RequestFactoryInterface`, `StreamFactoryInterface` and `UriFactoryInterface`. An `OAuthStorageInterface` and a PSR-3 logger instance are optional.
+First you'll need a PSR-18 compatible HTTP client, it should (at least) support [CURLOPT_SSL_VERIFYPEER](https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html) and have it enabled,
+for which it needs a valid certificate (or [certificate bundle](https://curl.se/docs/caextract.html)).
+
+**chillerlan/HTTP**
+
+```php
+$httpOptions = new \chillerlan\HTTP\HTTPOptions([
+ 'ca_info' => '/path/to/cacert.pem',
+ 'user_agent' => OAuthInterface::USER_AGENT,
+]);
+
+$http = new \chillerlan\HTTP\CurlClient(new ResponseFactory, $httpOptions);
+```
-Let's invoke a `GitHub` provider:
+**GuzzleHttp**
```php
+$httpOptions = [
+ 'verify' => '/path/to/cacert.pem',
+ 'headers' => [
+ 'User-Agent' => OAuthInterface::USER_AGENT,
+ ],
+];
+
+$http = new \GuzzleHttp\Client($httpOptions);
+```
+
+Now let's invoke a `GitHub` provider:
+```php
// now we can invoke the provider
$provider = new GitHub(
$options,
@@ -95,3 +121,31 @@ $provider = new GitHub(
);
```
+
+### Provider factory
+
+Invoking a provider can be a bit chunky and perhaps gets messy as soon as you're using more than one OAuth service in your project.
+In that case you can use the `OAuthProviderFactory` for convenience:
+
+```php
+// invoke the provider factory with the common PSR instances
+$providerFactory = new OAuthProviderFactory(
+ $http,
+ new RequestFactory,
+ new StreamFactory,
+ new UriFactory,
+ $logger, // optional
+);
+
+// invoke the provider instance - the $options and $storage params are optional
+$provider = $providerFactory->getProvider(GitHub::class, $options, $storage);
+```
+
+Additionally, the provider factory offers convenience methods to set a different logger instance and to get each of the PSR-17 factories:
+
+```php
+$providerFactory->setLogger(new NullLogger);
+$providerFactory->getRequestFactory();
+$providerFactory->getStreamFactory();
+$providerFactory->getUriFactory();
+```
diff --git a/docs/Usage/Using-examples.md b/docs/Usage/Using-examples.md
new file mode 100644
index 0000000..bc9912a
--- /dev/null
+++ b/docs/Usage/Using-examples.md
@@ -0,0 +1,107 @@
+# Using the examples
+
+OAuth is not exactly trivial and so is live testing an OAuth flow to make sure the implementation and all its details work as expected.
+The examples - specifically [the get-token examples](https://github.com/chillerlan/php-oauth/tree/main/examples/get-token) -
+are abstracted and condensed as far as possible to make using them as convenient as it can get.
+
+
+## Requirements
+
+### Server
+
+Due to the nature of OAuth callbacks, you will need a webserver with public access, or rather, that is accepted as callback URL
+by the service you're about to test, so `http://127.0.0.1/oauth/` will *definitely not* work - we'll assume
+`https://example.com/oauth/` as the public callback URL throughout the examples.
+
+Further we'll assume that `/var/www/` (with an associated user `webmaster`) is the directory that holds all web related files and dependencies,
+and `/var/www/htdocs/` is the root of the public website, which translates to `https://example.com/`, hence `/var/www/htdocs/oauth/` becomes the OAuth callback entrypoint at `https://example.com/oauth/`.
+A web framework would probably just have `/var/www/htdocs/index.php` as its entry point and route all requests through it,
+but that is not focus of this example.
+
+
+### Dependencies
+
+To install the required dependencies, create a `composer.json` in `/var/www/` with the following content and run `composer install` (as user `webmaster`):
+
+```json
+{
+ "require": {
+ "php": "^8.1",
+ "chillerlan/php-dotenv": "^3.0",
+ "chillerlan/php-oauth": "^1.0",
+ "guzzlehttp/guzzle": "^7.8",
+ "monolog/monolog": "^3.5"
+ }
+}
+```
+
+After that, copy the `examples` directory in the library root to `/var/www/oauth-examples/`.
+
+
+### Configuration
+
+We'll store the configuration files in the user directory under `/home/webmaster/oauth-config/`.
+The `FileStorage` in the `OAuthExampleProviderFactory` expects a `.filestorage` directory in the configuration directory
+with permissions set to at least `0755`, otherwise PHP's `is_writable()` will fail.
+
+The cacert is also expected in the configuration, so we'll fetch a fresh one directly into it:
+
+```shell
+curl -o /home/webmaster/oauth-config/cacert.pem https://curl.se/ca/cacert.pem
+```
+
+Finally, we need a `.env` file that contains the provider configuration. We'll [create an application on GitHub](https://github.com/settings/developers)
+and save the credentials - the naming convention is `_` where the prefix is `OAuthInterface::IDENTIFIER`.
+
+```
+GITHUB_KEY=
+GITHUB_SECRET=
+GITHUB_CALLBACK_URL=https://example.com/oauth/
+```
+
+
+## Run the authorization flow
+
+The call chain starts with the [`index.php`](https://github.com/chillerlan/php-oauth/blob/main/public/index.php) in `/var/www/htdocs/oauth/`.
+We'll need to adjust it to our example configuration from before:
+
+```php
+$AUTOLOADER = '/var/www/vendor/autoload.php';
+$CFGDIR = '/home/webmaster/oauth-config/';
+$ENVFILE = '.env';
+
+// additional parameters
+$PARAMS = [];
+// scopes to use with the given provider
+$SCOPES = [
+ GitHub::SCOPE_USER,
+ GitHub::SCOPE_PUBLIC_REPO,
+ GitHub::SCOPE_GIST,
+];
+
+// uncomment in case something goes wrong
+#error_reporting(E_ALL);
+#ini_set('display_errors', 1);
+
+require_once '/var/www/oauth-examples/get-token/GitHub.php';
+```
+
+You can now navigate to `https://example.com/oauth/` where you will be greeted with a link "Connect with GitHub!".
+
+### Call chain
+
+Let's break down what happens behind the scenes:
+
+1. the `index.php` initializes a set of variables and includes an example from `/var/www/oauth-examples/get-token/`, here `GitHub.php`
+2. `.php` includes [`/var/www/oauth-examples/provider-example-common.php`](https://github.com/chillerlan/php-oauth/blob/main/examples/provider-example-common.php), which:
+ - includes the composer autoloader given through `$AUTOLOADER`
+ - invokes the PSR-18 HTTP client, which is available as `$http`
+ - invokes the [`OAuthExampleProviderFactory`](https://github.com/chillerlan/php-oauth/blob/main/examples/OAuthExampleProviderFactory.php), which is available as `$factory`
+3. the OAuth provider is invoked via `$factory->getProvider(::class)` in `.php` and becomes available as `$provider`
+4. `.php` includes either `_flow-oauth1.php` or `_flow-oauth2.php` from `/var/www/oauth-examples/get-token/`
+5. the [authorization flow](./Authorization.md) is executed:
+ - redirect to the URL received from `$provider->getAuthorizationURL($PARAMS, $SCOPES)`
+ - the token request is called with the data from the incoming callback via `$provider->getAccessToken(...)`
+ - the access token is stored under `/home/webmaster/oauth-config/.filestorage` and is displayed in the output once access is granted
+
+Profit!
diff --git a/docs/index.rst b/docs/index.rst
index 9df6246..f1b45b3 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -26,6 +26,7 @@ This work is licensed under the Creative Commons Attribution 4.0 International (
Usage/Quickstart.md
Usage/Authorization.md
+ Usage/Using-examples.md
.. toctree::
:maxdepth: 3
@@ -34,7 +35,6 @@ This work is licensed under the Creative Commons Attribution 4.0 International (
Development/Create-provider.md
Development/Additional-functionality.md
Development/Test-suite.md
- Development/Using-examples.md
.. toctree::
:maxdepth: 3