Home > Back-end >  In new Google Identity Sign in for march 2023, JWT can't be decoded at uri_login (endpoint of a
In new Google Identity Sign in for march 2023, JWT can't be decoded at uri_login (endpoint of a

Time:10-02

The $_POST['credential'] value is the Json Web Token of callback API Google Identity Authentication handled in HTML and Console of Application Developper

in controller (route is the url gave in callback url in Google Console of the Api and Application):

#[Route('/connect/google/check', name: 'connect_google_check')]
public function connectCheckAction():Response
{
    $jwt = $request->request->get('credential');
    $match = explode( ".", $jwt);
        
dd(json_decode(base64_decode($match[0])),json_decode(base64_decode($match[1])),json_decode(base64_decode($match[2])));

}

gives:

{#1152 ▼
   "alg": "RS256"
   "kid": "ba079b4202641e54abced8fb1354ce03919fb294"
   "typ": "JWT"
},
null,
null

my html is:

<script nonce="{{ csp_nonce() }}" src="https://accounts.google.com/gsi/client" async defer></script>
    <meta name="google-signin-client_id" content="1671-a7dkj7lut6mhipeh94p618nej2peeg30.apps.googleusercontent.com">
<div >
    <div id="g_id_onload"
    data-client_id="1671-a7dkj7lut6mhipeh94p618nej2peeg30.apps.googleusercontent.com"
    data-login_uri="https://monticketperso.fr/login"
    data-auto_prompt="false"
    data-callback="handleCredentialResponse">
    </div>
    <div 
    data-type="standard"
    data-size="large"
    data-theme="outline"
    data-text="sign_in_with"
    data-shape="rectangular"
    data-logo_alignment="left">
    </div>
</div>

my Google auth2 is Google (SDK Google identity) -https://developers.google.com/identity/gsi/web/guides/overview

My configuration for application Share is:

.../auth/userinfo.email 
.../auth/userinfo.profile       
   openid

So don't need to integrate Authorization, but just implemented Authentication !!? I don'y know why the: json_decode(base64_decode(match[1])) and json_decode(base64_decode(match[2])) don't work ! if Any idea to solve this bug, it'll be great of you... Thank you... Cordially

Result of dd in controller

CodePudding user response:

That work now without using a bundle:

$jwt = $request->request->get('credential');
$match=explode('.',$jwt);

function base64url_decode($base64url)
{
   $base64 = strtr($base64url, '-_', ' /');
   $plainText = base64_decode($base64);
    return ($plainText);
}
  $payload=base64url_decode($match[1]);
  $payloadObject=json_decode($payload);

$verif = $payloadObject->email_verified;
$email = $payloadObject->email;

But now to authenticate the user, I've a null teturned X-AUTH-TOKEN header in the post callback... The function authenticate is like that:

public function authenticate(Request $request): PassportInterface
{
   $apiToken = $request->headers->get('X-AUTH-TOKEN');
    if (null === $apiToken) {
    // The token header was empty, authentication fails with HTTP Status
    // Code 401 "Unauthorized"
    throw new CustomUserMessageAuthenticationException('No API token provided');
     }

     return new SelfValidatingPassport(new UserBadge($apiToken));
}

And the post request has not X-AUTH-TOKEN header:

dd($request->headers->get('X-AUTH-TOKEN'));
//null

I find a lot of results on Google Search but some of them are not useful... If any idea ? Thank you ... Cordially

CodePudding user response:

Finally I recreated an Authenticator for Google and bypassed the need to have an X-AUTH-TOKEN header, so I authenticate the user through a Google controller which enters the user if it does not exist and my authenticator adds the user in the authentication process:

dans /src/Controller/GoogleController.php:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use App\Security\GoogleAuthenticator;

class GoogleController extends AbstractController
{
public function connectCheckAction(Request $request, UserPasswordHasherInterface $userPasswordHasher, UserAuthenticatorInterface $userAuthenticator, EntityManagerInterface $entityManager, GoogleAuthenticator $authenticator):Response
      {//...
       //...
      $userAuthenticator->authenticateUser(
      $existingUser,
      $authenticator,
      $request
     );
     }
}

et /src/Security/GoogleAuthenticator.php:

namespace App\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Routing\Annotation\Route;

class GoogleAuthenticator extends AbstractAuthenticator
{
    public function supports(Request $request): ?bool
    {
        // TODO: Implement supports() method.
        if($request->request->get('credentials')){
            return true;
        } else {
            return false;
        }
    }

    public function authenticate(Request $request): PassportInterface
    {
        // TODO: Implement authenticate() method.
        $jwt = $request->request->get('credential');
        $match=explode('.',$jwt);

        function base64url_decode($base64url)
        {
            $base64 = strtr($base64url, '-_', ' /');
            $plainText = base64_decode($base64);
            return ($plainText);
        }
        //dd($jwt, base64url_decode($match[0]),base64url_decode($match[1]),base64url_decode($match[2]));
        $payload=base64url_decode($match[1]);
        $payloadObject=json_decode($payload);
        //dd($payloadObject);
        if($payloadObject->email_verified===true){
            //recupere email du jwt
            return new SelfValidatingPassport(new UserBadge($match[1]));
        } else {
            throw new CustomUserMessageAuthenticationException('No API token provided');
        }
        //return new SelfValidatingPassport(new UserBadge($apiToken));
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName):?Response
    {
        // TODO: Implement onAuthenticationSuccess() method.
        return null;
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
    {
        // TODO: Implement onAuthenticationFailure() method.
        return new RedirectResponse($this->router->generate('error404'));
    }

//    public function start(Request $request, AuthenticationException $authException = null): Response
//    {
//        /*
//         * If you would like this class to control what happens when an anonymous user accesses a
//         * protected page (e.g. redirect to /login), uncomment this method and make this class
//         * implement Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface.
//         *
//         * For more details, see https://symfony.com/doc/current/security/experimental_authenticators.html#configuring-the-authentication-entry-point
//         */
//    }
}

et dans config/packages/security.yaml:

security:
    firewalls:
        main:
            custom_authenticators:
                - App\Security\AppCustomAuthenticator
                - App\Security\GoogleAuthenticator
  • Related