stevenmaguire / oauth2-microsoft

Microsoft OAuth 2.0 support for the PHP League's OAuth 2.0 Client
MIT License
68 stars 41 forks source link

Where is the error? #26

Open ElUtku opened 10 months ago

ElUtku commented 10 months ago

Hi,

I'm trying to implement the method but i get the error "AADSTS9002325: Proof Key for Code Exchange is required for cross-origin authorization code redemption." and i don't caught what is wrong...

Edit: I think that the problem is that 'pkceMethod' => Microsoft::PKCE_METHOD_S256 is not allowed in this adapter, so it isn't send with the petition.

$provider = new Microsoft([
            // Required
            'clientId'                  => 'xxxxx',
            'clientSecret'              => 'xxxxx',
            'redirectUri'               => 'xxxxx',
            // Optional
            'urlAuthorize'              => 'https://login.windows.net/common/oauth2/authorize',
            'urlAccessToken'            => 'https://login.windows.net/common/oauth2/token',
            'urlResourceOwnerDetails'   => 'https://outlook.office.com/api/v1.0/me',
            'pkceMethod' => Microsoft::PKCE_METHOD_S256
        ]);

        if (!isset($_GET['code'])) {

            // If we don't have an authorization code then get one
            $authUrl = $provider->getAuthorizationUrl();
            $_SESSION['oauth2state'] = $provider->getState();
            $_SESSION['oauth2pkceCode'] = $provider->getPkceCode();
            header('Location: '.$authUrl);
            exit;

// Check given state against previously stored one to mitigate CSRF attack
        } elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {

            if (isset($_SESSION['oauth2state'])) {
                unset($_SESSION['oauth2state']);
            }

            exit('Fallo al principio...');

        } else {

            // Try to get an access token (using the authorization code grant)
            try {
                $provider->setPkceCode($_SESSION['oauth2pkceCode']);
                $token = $provider->getAccessToken('authorization_code', [
                    'code' => $_GET['code']
                ]);

            } catch (IdentityProviderException $e) {
                echo $e;
                exit('Fallo por el medio... || ' . $e->getMessage());
            }

            // Optional: Now you have a token you can look up a users profile data
            try {

                // We got an access token, let's now get the user's details
                $user = $provider->getResourceOwner($token);

                // Use these details to create a new profile
                printf('Hello %s!', $user->getFirstname());

            } catch (Exception $e) {

                // Failed to get user details
                exit('Fallo casi al final...');
            }

            // Use this to interact with an API on the users behalf
            echo $token->getToken();
        }
decomplexity commented 10 months ago

Since Steve Maguire's provider hasn't - unless I have missed it - been updated since 2015-16 and the RFC for 'pixie' was only issued in 2015, it is possible that this provider does not support it. Pixie support for Ben Ramsey's TheLeague's oauth2-client on which the Maguire provider depends was only added in April this year (see its Generic provider). I see from GitHub email that you have now edited the 'pkceMethod' => Microsoft to 'pkceMethod' => GenericProvider, but will you then need to instantiate GenericProvider (as well as Maguire'e provider)? If so, will you then get conflicts between any other public methods or properties in these two? You may need to copy the relevant pixie code from Generic and Abstract providers and create a trait, because pkceMethod in GenericProvider has 'private' visibility (but - as I guess you will have seen - there is a PKCE setter and a getter in AbstractProvider)

And a rather obvious point: I haven't checked the Generic or Abstract provider code, but does setting 'pkceMethod' when instantiating the provider set the PKCE method AND add the codeChallenge and codeChallengeMethod to the authorization endpoint URL or merely tell the provider that you will be using PKCE?