Skip to content

Commit

Permalink
okta method for refreshing tokens (#808)
Browse files Browse the repository at this point in the history
  • Loading branch information
clink-aaron authored Mar 15, 2022
0 parents commit 7522b27
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 0 deletions.
18 changes: 18 additions & 0 deletions AzureExtendSocialite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace SocialiteProviders\Azure;

use SocialiteProviders\Manager\SocialiteWasCalled;

class AzureExtendSocialite
{
/**
* Register the provider.
*
* @param \SocialiteProviders\Manager\SocialiteWasCalled $socialiteWasCalled
*/
public function handle(SocialiteWasCalled $socialiteWasCalled)
{
$socialiteWasCalled->extendSocialite('azure', Provider::class);
}
}
139 changes: 139 additions & 0 deletions Provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php

namespace SocialiteProviders\Azure;

use GuzzleHttp\RequestOptions;
use SocialiteProviders\Manager\OAuth2\AbstractProvider;
use SocialiteProviders\Manager\OAuth2\User;

class Provider extends AbstractProvider
{
/**
* Unique Provider Identifier.
*/
public const IDENTIFIER = 'AZURE';

/**
* The base Azure Graph URL.
*
* @var string
*/
protected $graphUrl = 'https://graph.microsoft.com/v1.0/me';

/**
* {@inheritdoc}
*/
protected $scopeSeparator = ' ';

/**
* The scopes being requested.
*
* @var array
*/
protected $scopes = ['User.Read'];

/**
* {@inheritdoc}
*/
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase($this->getBaseUrl().'/oauth2/v2.0/authorize', $state);
}

/**
* Return the logout endpoint with post_logout_redirect_uri query parameter.
*
* @param string $redirectUri
*
* @return string
*/
public function getLogoutUrl(string $redirectUri)
{
return $this->getBaseUrl()
.'/oauth2/logout?'
.http_build_query(['post_logout_redirect_uri' => $redirectUri], '', '&', $this->encodingType);
}

/**
* {@inheritdoc}
*/
protected function getTokenUrl()
{
return $this->getBaseUrl().'/oauth2/v2.0/token';
}

public function getAccessToken($code)
{
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
RequestOptions::FORM_PARAMS => $this->getTokenFields($code),
]);

$this->credentialsResponseBody = json_decode((string) $response->getBody(), true);

return $this->parseAccessToken($response->getBody());
}

/**
* {@inheritdoc}
*/
protected function getUserByToken($token)
{
$response = $this->getHttpClient()->get($this->graphUrl, [
RequestOptions::HEADERS => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$token,
],
RequestOptions::PROXY => $this->getConfig('proxy'),
]);

return json_decode((string) $response->getBody(), true);
}

/**
* {@inheritdoc}
*/
protected function mapUserToObject(array $user)
{
return (new User())->setRaw($user)->map([
'id' => $user['id'],
'nickname' => null,
'name' => $user['displayName'],
'email' => $user['userPrincipalName'],
'avatar' => null,
]);
}

/**
* Get the access token response for the given code.
*
* @param string $code
*
* @return array
*/
public function getAccessTokenResponse($code)
{
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
RequestOptions::HEADERS => ['Accept' => 'application/json'],
RequestOptions::FORM_PARAMS => $this->getTokenFields($code),
RequestOptions::PROXY => $this->getConfig('proxy'),
]);

return json_decode($response->getBody(), true);
}

/**
* @return string
*/
protected function getBaseUrl(): string
{
return 'https://login.microsoftonline.com/'.$this->getConfig('tenant', 'common');
}

/**
* {@inheritdoc}
*/
public static function additionalConfigKeys()
{
return ['tenant', 'proxy'];
}
}
92 changes: 92 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Azure

```bash
composer require socialiteproviders/microsoft-azure
```

## Installation & Basic Usage

Please see the [Base Installation Guide](https://socialiteproviders.com/usage/), then follow the provider specific instructions below.

### Add configuration to `config/services.php`

```php
'azure' => [
'client_id' => env('AZURE_CLIENT_ID'),
'client_secret' => env('AZURE_CLIENT_SECRET'),
'redirect' => env('AZURE_REDIRECT_URI'),
'tenant' => env('AZURE_TENANT_ID'),
'proxy' => env('PROXY') // optionally
],
```

### Add provider event listener

Configure the package's listener to listen for `SocialiteWasCalled` events.

Add the event to your `listen[]` array in `app/Providers/EventServiceProvider`. See the [Base Installation Guide](https://socialiteproviders.com/usage/) for detailed instructions.

```php
protected $listen = [
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
// ... other providers
\SocialiteProviders\Azure\AzureExtendSocialite::class.'@handle',
],
];
```

### Usage

You should now be able to use the provider like you would regularly use Socialite (assuming you have the facade installed):

```php
return Socialite::driver('azure')->redirect();
```

To logout of your app and Azure:
```php
public function logout(Request $request)
{
Auth::guard()->logout();
$request->session()->flush();
$azureLogoutUrl = Socialite::driver('azure')->getLogoutUrl(route('login'));
return redirect($azureLogoutUrl);
}
```

### Returned User fields

- ``id``
- ``name``
- ``email``

## Advanced usage

In order to have multiple / different Active directories on Azure (i.e. multiple tenants) The same driver can be used but with a different config:

```php
/**
* Returns a custom config for this specific Azure AD connection / directory
* @return \SocialiteProviders\Manager\Config
*/
function getConfig(): \SocialiteProviders\Manager\Config
{
return new \SocialiteProviders\Manager\Config(
env('AD_CLIENT_ID', 'some-client-id'), // a different clientID for this separate Azure directory
env('AD_CLIENT_SECRET'), // a different secret for this separate Azure directory
url(env('AD_REDIRECT_PATH', '/azuread/callback')), // the redirect path i.e. a different callback to the other azureAD callbacks
['tenant' => env('AD_TENTANT_ID', 'common')], // this could be something special if need be, but can also be left out entirely
);
}
//....//
Socialite::driver('azure')
->setConfig(getConfig())
->redirect();
```

This also applies to the callback for getting the user credentials that one has to remember to inject the ```->setConfig($config)```-method i.e.:
```php
$socialUser = Socialite::driver('azure')
->setConfig(getConfig())
->user();
```
34 changes: 34 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "socialiteproviders/microsoft-azure",
"description": "Microsoft Azure OAuth2 Provider for Laravel Socialite",
"keywords": [
"azure",
"laravel",
"microsoft",
"oauth",
"provider",
"socialite"
],
"license": "MIT",
"authors": [
{
"name": "Chris Hemmings",
"email": "chris@hemmin.gs"
}
],
"require": {
"php": "^7.2 || ^8.0",
"ext-json": "*",
"socialiteproviders/manager": "~4.0"
},
"autoload": {
"psr-4": {
"SocialiteProviders\\Azure\\": ""
}
},
"support": {
"issues": "https://github.com/socialiteproviders/providers/issues",
"source": "https://github.com/socialiteproviders/providers",
"docs": "https://socialiteproviders.com/microsoft-azure"
}
}

0 comments on commit 7522b27

Please sign in to comment.