2

I am trying to use AWS Cognito hosted UI with WordPress. i am successful to load sign-in page and after login it redirects to given redirect_url along with id_token like

http://example.com/#id_token=eyJraWQiOiJvYzVvK3pwRTFrRHJFYmE0 ...

i am unable to get #id_token in my php code where i need to verify & load my local user for wordpress-php site.

any help is much appreciated

below is my plugin code

<?php

global $login_page;
$login_page = 'https://example.auth.eu-central-1.amazoncognito.com/login?response_type=token&client_id=xxxxxxxx';
$login_page .= '&redirect_uri=http://localhost/example.com';

add_action('init','goto_login_page');
add_filter( 'auth_cookie_malformed', 'check_authentication_token' );

function goto_login_page() {

    global $login_page;
    $page = basename($_SERVER['REQUEST_URI']);
    if (isset($_GET['#id_token'])) {
       $jwt = $_GET['#id_token'];
       $publicKey = '';
       $decoded = JWT::decode($jwt, $publicKey, array('RS256'));
    }
    else if( $page == "wp-login.php" && $_SERVER['REQUEST_METHOD'] == 'GET') {
        wp_redirect($login_page);
        exit;
    }
}

function check_authentication_token() {

    global $login_page;
    if (isset($_GET['#id_token'])) {
        $jwt = $_GET['#id_token'];
        $publicKey = '';
        $decoded = JWT::decode($jwt, $publicKey, array('RS256'));
        die;
    }
    else {
        var_dump("");
    }
}

i am trying to use some filters to override WordPress login stuff with AWS Cognito hosted UI

Yogesh Salvi
  • 1,177
  • 2
  • 10
  • 17
  • Have you tried to use the `$_GET["id_token"]` ? – Gangai Johann Aug 13 '18 at 10:13
  • post the code of what you have done so far to solve this issue – Anantha Raju C Aug 13 '18 at 10:14
  • `$_GET["id_token"]` didn't work, i cant see `id_token` in session/cokkie/get params either – Atieq ur Rehman Aug 13 '18 at 10:25
  • 1
    I can tell you anything after the `#` which is called a fragment, is not sent to the server. See also https://stackoverflow.com/questions/14462218/is-the-url-fragment-identifier-sent-to-the-server what this means is PHP never gets that data. How you deal with that I cannot say. But that is the reason its not in `$_REQUEST` or any of the super global arrays, sorry. – ArtisticPhoenix Aug 13 '18 at 10:36
  • Here is a better post about fragments.. https://stackoverflow.com/questions/940905/can-i-read-the-hash-portion-of-the-url-on-my-server-side-application-php-ruby Probably the only thing you can do is work with it clientside and maybe pass it via AJAX, it's over complicated and messy though. – ArtisticPhoenix Aug 13 '18 at 10:42
  • then i believe its not the right way to do authentication. I am confused above why AWS Cognito sends response in this form, or what better ways can be to achieve user authentication – Atieq ur Rehman Aug 13 '18 at 10:52

1 Answers1

3

after doing multiple experiments it turned out that i should use different approach to perform login through back-end API calls. Below are the steps to be followed

  1. user response_type=code this will response with an authorization code and the use code to get token [id_token, access_token, refresh_token] i.e.


    function get_token() {

    if(isset($_GET['code'])) {
            $data = array(
                'code' => $_GET['code'],
                'client_id' => $client_id,
                'grant_type' => 'authorization_code',
                'scope' => 'email profile openid',
                'redirect_uri' => $redirect_uri,
                'client_secret' => $client_secret
            );

            $jwt = httpPost($base_url . '/oauth2/token', $data);
            return $jwt;
        }
    }

  1. decode response to JSON json_decode($jwt)

  2. get public key like below method



    function get_public_key() {
        global $region, $pool_id;

        return json_decode(file_get_contents('https://cognito-idp.' . $region . '.amazonaws.com/' . $pool_id . '/.well-known/jwks.json'));
    }

  1. validate & extract payload using code like


    foreach ($publicKey->keys as $key) {
            try {

                $pk = JWK::parseKey($key);

                $pay_load = JWT::decode($jwt_json->id_token, $pk, array('RS256'));

                if($pay_load !== '') {
                    return  get_object_vars($pay_load);
                }
            }
            catch (Exception $e) {
                error_log($e->getMessage());
            }
        }

please note that JWK class can be taken from https://github.com/fproject/php-jwt as its not part of firebase\php-jwt