Skip to content

#22 expose refresh token in response headers #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 69 additions & 19 deletions src/ManageTokens.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace WPGraphQL\JWT_Authentication;

use GraphQL\Error\UserError;
Expand Down Expand Up @@ -52,10 +53,21 @@ public static function init() {
'\WPGraphQL\JWT_Authentication\ManageTokens',
'add_tokens_to_graphql_response_headers'
] );

add_filter( 'graphql_response_headers_to_send', [
'\WPGraphQL\JWT_Authentication\ManageTokens',
'add_auth_headers_to_response'
] );

add_filter( 'graphql_access_control_allow_headers', [
'\WPGraphQL\JWT_Authentication\ManageTokens',
'add_jwt_allowed_headers'
] );
}

/**
* Filters the User type in the GraphQL Schema to provide fields for querying for user's jwtAuthToken and jwtUserSecret
* Filters the User type in the GraphQL Schema to provide fields for querying for user's
* jwtAuthToken and jwtUserSecret
*
* @param array $fields The fields for the User type in the GraphQL Schema
*
Expand All @@ -64,9 +76,9 @@ public static function init() {
public static function add_user_fields( $fields ) {

$fields['jwtAuthToken'] = [
'type' => Types::string(),
'type' => Types::string(),
'description' => __( 'A JWT token that can be used in future requests for authentication/authorization', 'wp-graphql-jwt-authentication' ),
'resolve' => function( \WP_User $user ) {
'resolve' => function ( \WP_User $user ) {

/**
* Get the token for the user
Expand All @@ -85,9 +97,9 @@ public static function add_user_fields( $fields ) {
];

$fields['jwtRefreshToken'] = [
'type' => Types::string(),
'type' => Types::string(),
'description' => __( 'A JWT token that can be used in future requests to get a refreshed jwtAuthToken. If the refresh token used in a request is revoked or otherwise invalid, a valid Auth token will NOT be issued in the response headers.', 'wp-graphql-jwt-authentication' ),
'resolve' => function( \WP_User $user ) {
'resolve' => function ( \WP_User $user ) {

/**
* Get the token for the user
Expand All @@ -106,9 +118,9 @@ public static function add_user_fields( $fields ) {
];

$fields['jwtUserSecret'] = [
'type' => Types::string(),
'type' => Types::string(),
'description' => __( 'A unique secret tied to the users JWT token that can be revoked or refreshed. Revoking the secret prevents JWT tokens from being issued to the user. Refreshing the token invalidates previously issued tokens, but allows new tokens to be issued.', 'wp-graphql' ),
'resolve' => function( \WP_User $user ) {
'resolve' => function ( \WP_User $user ) {

/**
* Get the user's JWT Secret
Expand All @@ -130,53 +142,55 @@ public static function add_user_fields( $fields ) {
];

$fields['jwtAuthExpiration'] = [
'type' => Types::string(),
'type' => Types::string(),
'description' => __( 'The expiration for the JWT Token for the user. If not set custom for the user, it will use the default sitewide expiration setting', 'wp-graphql-jwt-authentication' ),
'resolve' => function( \WP_User $user ) {
'resolve' => function ( \WP_User $user ) {
$expiration = Auth::get_token_expiration();

return ! empty( $expiration ) ? $expiration : null;
}
];

$fields['isJwtAuthSecretRevoked'] = [
'type' => Types::non_null( Types::boolean() ),
'type' => Types::non_null( Types::boolean() ),
'description' => __( 'Whether the JWT User secret has been revoked. If the secret has been revoked, auth tokens will not be issued until an admin, or user with proper capabilities re-issues a secret for the user.', 'wp-graphql-jwt-authentication' ),
'resolve' => function( \WP_User $user ) {
'resolve' => function ( \WP_User $user ) {
$revoked = Auth::is_jwt_secret_revoked( $user->ID );

return true == $revoked ? true : false;
}
];



return $fields;

}

/**
* Given an array of fields, this returns an array with the new fields added
*
* @param array $fields The input fields for user mutations
*
* @return array
*/
public static function add_user_mutation_input_fields( array $fields ) {

$fields['revokeJwtUserSecret'] = [
'type' => Types::boolean(),
'type' => Types::boolean(),
'description' => __( 'If true, this will revoke the users JWT secret. If false, this will unrevoke the JWT secret AND issue a new one. To revoke, the user must have proper capabilities to edit users JWT secrets.', 'wp-graphql-jwt-authentication' ),
];

$fields['refreshJwtUserSecret'] = [
'type' => Types::boolean(),
'type' => Types::boolean(),
'description' => __( 'If true, this will refresh the users JWT secret.' ),
];

return $fields;
}

/**
* @param int $user_id The ID of the user being mutated
* @param array $input The input args of the GraphQL mutation request
* @param int $user_id The ID of the user being mutated
* @param array $input The input args of the GraphQL mutation request
* @param string $mutation_name The name of the mutation
*/
public static function update_jwt_fields_during_mutation( $user_id, array $input, $mutation_name ) {
Expand Down Expand Up @@ -208,11 +222,11 @@ public static function update_jwt_fields_during_mutation( $user_id, array $input
* This filters the token to prevent it from being issued if it has been revoked.
*
* @param string $token
* @param int $user_id
* @param int $user_id
*
* @return string $token
*/
public static function prevent_token_from_returning_if_revoked( $token, $user_id ) {
public static function prevent_token_from_returning_if_revoked( $token, $user_id ) {

/**
* Check to see if the user's auth secret has been revoked.
Expand Down Expand Up @@ -254,6 +268,14 @@ public static function use_custom_user_expiration( $expiration ) {

}

/**
* Returns tokens in the response headers
*
* @param $headers
*
* @return mixed
* @throws \Exception
*/
public static function add_tokens_to_graphql_response_headers( $headers ) {

/**
Expand Down Expand Up @@ -296,4 +318,32 @@ public static function add_tokens_to_graphql_response_headers( $headers ) {

}

}
/**
* Expose the X-JWT-Refresh tokens in the response headers. This allows
* folks to grab new refresh tokens from authenticated requests for subsequent use.
*
* @param array $headers The existing response headers
*
* @return array
*/
public static function add_auth_headers_to_response( array $headers ) {
$headers['Access-Control-Expose-Headers'] = 'X-JWT-Refresh';

return $headers;
}

/**
* Expose the X-JWT-Auth and X-JWT-Refresh as allowed headers in GraphQL responses
*
* @param array $allowed_headers The existing allowed headers
*
* @return array
*/
public static function add_jwt_allowed_headers( array $allowed_headers ) {
$allowed_headers[] = 'X-JWT-Auth';
$allowed_headers[] = 'X-JWT-Refresh';

return $allowed_headers;
}

}