TheNetworg / oauth2-azure

Azure AD provider for the OAuth 2.0 Client.
https://packagist.org/packages/thenetworg/oauth2-azure
MIT License
230 stars 108 forks source link

Get a token with a Username and a Password #125

Closed MaxenceSAUNIER closed 3 years ago

MaxenceSAUNIER commented 3 years ago

Hello,

I have a question. I would like to link the AD of my company to our API manager so that it can be used to authenticate the users of enos different applications. however, we do not have control over all of them which prevents us for the moment from directly connecting a redirect to the Microsoft authentication page for authentication. So I would like the username and password to pass through a POST request in TLS to my API solution and that I request a Token using these 2 pieces of information. Currently, here is my code:

<?php

namespace App\Controller;

use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use TheNetworg\OAuth2\Client\Provider\Azure as AzureProvider;

/**
 * Class SmtPlzController
 * @package App\Controller
 * @Route("/bazuregate", name="smtplz_")
 */
class BAzureGateController extends AbstractController
{

    /**
     * @Route("/{client_domain}", name="login",
     *     methods={"POST"},
     *     requirements={
     *          "client_domain"="^[A-Za-z]+\.[A-Za-z]+$"
     *     },
     *     format="json")
     * @param string $client_domain
     * @param LoggerInterface $logger
     * @param Request $request
     * @return void
     */
    public function Login(string $client_domain, LoggerInterface $logger, Request $request)
    {
        $provider = new AzureProvider([
            'clientId'              => $this->getParameter("azure.client.id"),
            'clientSecret'     => $this->getParameter("azure.client.secret"),
            'redirectUri'       => $request->getUri(),
            'urlAuthorize'  => 'https://login.microsoftonline.com/'.$this->getParameter('azure.tenant.id').'/oauth2/v2.0/authorize',
            'urlAccessToken' => 'https://login.microsoftonline.com/'.$this->getParameter('azure.tenant.id').'/oauth2/v2.0/token'
        ]);

        $provider->defaultEndPointVersion = AzureProvider::ENDPOINT_VERSION_2_0;

        try {
            $accessToken = $provider->getAccessToken('password', [
                'username' => $request->request->get('username'),
                'password' => $request->request->get('password')
            ]);
            exit($accessToken);

        } catch (IdentityProviderException $e) {

            // Failed to get the access token
            exit($e->getMessage());

        }
    }
}

And the response :

invalid_request
AADSTS9001023: The grant type is not supported over the /common or /consumers endpoints. Please use the /organizations
or tenant-specific endpoint.

What could be the solution to this problem? Thanks in advance.

Maxence,

decomplexity commented 3 years ago

I assume that since the 'access token' calls are coming from your API manager and not from the user client, the token endpoint is treating the request as ROPC - which is does not support /common or /consumers. Whether you can rejig your API Manager to act using client credentials grants instead I cannot comment, but this may create its own problems (e.g. client SMTP AUTH is not supported.). You have, I imagine, already looked at the B2C options to allow users to authenticate via the SAML or OIDC service of their choice?

hajekj commented 3 years ago

Hi, if I were you, I would stay away from ROPC flow. It doesn't allow for MFA, password-less and bunch of other security features like sign-in risk won't be properly evaluated etc.

MaxenceSAUNIER commented 3 years ago

Hello, Thank you very much for your answers! I will learn more about SAML and OIDC, I was able to do some conclusive tests on Friday with SAML. All this is relatively vague and it is relatively complicated to navigate through these different authentication methods, and you have been able to provide me with the necessary answers to my progress. You can close this post as I will now be able to search for the rest on my own. I would reopen it if I am missing any information :)

Thank you.

hajekj commented 3 years ago

Feel free to come back with questions. A good place to start would be either Microsoft's docs or The 425 Show where a lot of authentication related stuff is discussed.

If possible, go with OIDC, that's where the most innovation is.

Also a very good resource for me was this book: Modern Authentication with Azure Active Directory for Web Applications by Vittorio Bertocci, where a lot of protocol related things are explained.

ziggurad commented 3 years ago

Sorry that maybe not entirely on the topic, but @decomplexity mentioned SAML. Is it possible to log in using SAML through TheNetworg / oauth2-azure in conjunction with knpuniversity/oauth2-client-bundle?

hajekj commented 3 years ago

This library is unable to consume SAML protocol. What would be the usecase?

ziggurad commented 3 years ago

@hajekj Thank you for your response.

I need to implement logging (Microfot Azure, Single sign-on by SAML) in Pimcore Framework.

I wanted to use Pimcore members where to SSO I need KnpUOAuth2ClientBundle. But from what I can see there is no such possibility.

hajekj commented 3 years ago

I understand that, but why the need SAML - is it some corporate requirement? You should probably go with OAuth2 or OpenID Connect which is used in the bundle you mentioned.

/cc: @ziggurad

ziggurad commented 3 years ago

@hajekj

Yes, it is corporate requirement. I will come back to the person who presented such requirements to find out more.

hajekj commented 3 years ago

Awesome. I don't think using OpenID Connect should have any downsides, generally, it offers much more flexibility with what can be done. If you still needed to go with SAML, I think you will have to figure out another library like SimpleSamlPhp which is one of the most popular for SAML.

But as far as I know, you won't really be able to consume other APIs, since SAML doesn't provide tokens (for Microsoft Graph or other APIs).