Skip to content

alancting/oauth2-microsoft-openid

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Packagist GitHub Test Coverage Status GitHub license

Microsoft Adfs / AzureAD OpenId Integration for Symfony

Microsoft Azure Active Directory (Azure AD), Microsoft Active Directory Federation Services (Adfs) OpenId Integration for Symfony

  • Login with Adfs / AzureAd
    • All token handling is wrapped in the guard authenticator
  • Easy to get the stored tokens from a registered service

This bundle integrates with knpuniversity/oauth2-client-bundle

This package provides Microsoft OAuth 2.0 support for the PHP League's OAuth 2.0 Client.

Forked From stevenmaguire/oauth2-microsoft

Installation

To install, use composer:

composer require alancting/oauth2-microsoft-openid

Get Start

Step 1 - Include in the bundles

# config/bundles.php
return [
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    ...
    Alancting\OAuth2\OpenId\Client\MicrosoftBundle::class => ['all' => true],
];

Step 2 - Configure the provider

We make use of the configuration from knpuniversity/oauth2-client-bundle

Adfs

# config/packages/knpu_oauth2_client.yaml
knpu_oauth2_client:
  clients:
    microsoft_openid:
      type: generic
      provider_class: Alancting\OAuth2\OpenId\Client\Provider\AdfsProvider
      client_class: Alancting\OAuth2\OpenId\Client\Client\AdfsClient
      client_id: "%env(ADFS_CLIENT_ID)%"
      client_secret: "%env(ADFS_CLIENT_SECRET)%"
      redirect_route: microsoft_openid_connect
      provider_options:
        hostname: "%env(ADFS_HOSTNAME)%"
        user_key: unique_name
        microsoft_resource_scopes:
          - profile
          - offline_access
        other_resource_scopes:
          - "%env(ADFS_API_RESOURCE_1)%"
          - "%env(ADFS_API_RESOURCE_2)%"

Azure Ad

# config/packages/knpu_oauth2_client.yaml
knpu_oauth2_client:
  clients:
    microsoft_openid:
      type: generic
      provider_class: Alancting\OAuth2\OpenId\Client\Provider\AzureAdProvider
      client_class: Alancting\OAuth2\OpenId\Client\Client\AzureAdClient
      client_id: "%env(AZURE_AD_CLIENT_ID)%"
      client_secret: "%env(AZURE_AD_CLIENT_SECRET)%"
      redirect_route: microsoft_openid_connect
      provider_options:
        tenant: "%env(AZURE_AD_TENANT)%"
        tenant_id: "%env(AZURE_AD_TENANT_ID)%"
        user_key: upn
        microsoft_resource_scopes:
          - profile
          - offline_access
        other_resource_scopes:
          - "%env(AZURE_AD_API_RESOURCE_1)%"
          - "%env(AZURE_AD_API_RESOURCE_2)%"

Step 3 - Configure the use authenticator

Adfs

# config/packages/security.yaml
security:
  providers:
    microsoft_openid_oauth:
      id: alancting.microsoft.user_provider
  firewalls:
    secure_firewall:
        pattern: ^/([a-z])
          anonymous: ~
          logout:
            path: microsoft_openid_logout
            success_handler: App\Utility\LogoutHandler
          guard:
            provider: microsoft_openid_oauth
            authenticators:
              - alancting.microsoft.adfs.authenticator

Azure Ad

# config/packages/security.yaml
security:
  providers:
    microsoft_openid_oauth:
      id: alancting.microsoft.user_provider
  firewalls:
    secure_firewall:
        pattern: ^/([a-z])
          anonymous: ~
          logout:
            path: microsoft_openid_logout
            success_handler: App\Utility\LogoutHandler
          guard:
            provider: microsoft_openid_oauth
            authenticators:
              - alancting.microsoft.azure_ad.authenticator

Step 4 - Register pathsserver

We need to register two path to communicate with the OAuth2 server

  1. connect
  2. logout

Adfs

namespace App\Controller;

use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;

class AdfsController extends AbstractController
{
    /**
     * After going to microsoft, you're redirected back here
     * because this is the "redirect_route" you configured
     * in config/packages/knpu_oauth2_client.yaml
     *
     * @Route("/adfs/connect", name="microsoft_openid_connect")
     */
    public function connectCheckAction(Request $request, ClientRegistry $clientRegistry)
    {
        return new Response();
    }

    /**
     * After going to microsoft, you're redirected back here
     * because this is the "redirect_route" you configured
     * in config/packages/knpu_oauth2_client.yaml
     *
     * @Route("/adfs/logout", name="microsoft_openid_logout")
     */
    public function logoutAction(Request $request, ClientRegistry $clientRegistry)
    {
        return new Response();
    }
}

Azure Ad

namespace App\Controller;

use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;

class AzureAdController extends AbstractController
{
    /**
     * After going to microsoft, you're redirected back here
     * because this is the "redirect_route" you configured
     * in config/packages/knpu_oauth2_client.yaml
     *
     * @Route("/azure_ad/connect", name="microsoft_openid_connect")
     */
    public function connectCheckAction(Request $request, ClientRegistry $clientRegistry)
    {
        return new Response();
    }

    /**
     * After going to microsoft, you're redirected back here
     * because this is the "redirect_route" you configured
     * in config/packages/knpu_oauth2_client.yaml
     *
     * @Route("/azure_ad/logout", name="microsoft_openid_logout")
     */
    public function logoutAction(Request $request, ClientRegistry $clientRegistry)
    {
        return new Response();
    }
}

Usage

After user login,

  • You can get the login credentials
  • User is logged in with the roles: ROLE_USER and ROLE_OAUTH_USER

Adfs

use Alancting\OAuth2\OpenId\Client\Client\AdfsClient;

public index(AdfsClient $adfsClient)
{
    /**
     * Get credential for main scope
     */
    $mainScopeCredential = $adfsClient->getOAuthCredential();

    // Get access token
    $accessToken = $mainScopeCredential->getAccessToken();
    // Get id token
    $idTokenJWT = $mainScopeCredential->getIdTokenJWT();
    // Get id token payload
    $idTokenPayload = $idTokenJWT->getPayload();
    // Get value for a specific attr from id token payload
    $idTokenPayloadAttr1 = $idTokenJWT->get('attr1');

    /**
     * If have other resource scopes, you can loop to fetch credentials for other scopes
     */
    $otherScopeCredentials = [];
    foreach ($mainScopeCredential->getOtherResourceCredentials() as $scope => $credential) {
        $otherScopeCredentials[$scope] = $credential;
    }

    /**
     * You can also get the credential from scope name by
     */
    $otherScopeCredential = $mainScopeCredential->getOtherResourceCredential('other_scope_name');
}

Azure Ad

use Alancting\OAuth2\OpenId\Client\Client\AzureAdClient;

public index(AzureAdClient $azureAdClient)
{
    /**
     * Get credential for main scope
     */
    $mainScopeCredential = $azureAdClient->getOAuthCredential();

    // Get access token
    $accessToken = $mainScopeCredential->getAccessToken();
    // Get id token
    $idTokenJWT = $mainScopeCredential->getIdTokenJWT();
    // Get id token payload
    $idTokenPayload = $idTokenJWT->getPayload();
    // Get value for a specific attr from id token payload
    $idTokenPayloadAttr1 = $idTokenJWT->get('attr1');

    /**
     * If have other resource scopes, you can loop to fetch credentials for other scopes
     */
    $otherScopeCredentials = [];
    foreach ($mainScopeCredential->getOtherResourceCredentials() as $scope => $credential) {
        $otherScopeCredentials[$scope] = $credential;
    }

    /**
     * You can also get the credential from scope name by
     */
    $otherScopeCredential = $mainScopeCredential->getOtherResourceCredential('other_scope_name');
}

Logout Handling

In symfony, to logout a user, you should use

  • 4.4: Logout success handler
  • 5.x+: Logout event

After your app go to logout handler / event, you should redirect user to the Adfs / Azure AD logout Url, you can get the url by

// Logout url for Adfs
$logoutUrl = $adfsClient->getLogoutUrl();

// Logout url for Azure Ad
$logoutUrl = $azureAdClient->getLogoutUrl();

Tests

Run the tests using phpunit:

$ composer install
$ composer run test

Contributing

Please see CONTRIBUTING for details.

Credits

License

The MIT License (MIT). Please see License File for more information.

About

Microsoft OAuth 2.0 support for the PHP League's OAuth 2.0 Client

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 100.0%