Skip to content

Commit 7c59068

Browse files
committed
add refresh endpoint for auth token
1 parent 96db01e commit 7c59068

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

includes/API/Auth.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace WCPOS\WooCommercePOS\API;
1212

13+
use WCPOS\WooCommercePOS\Services\Auth as AuthService;
1314
use const WCPOS\WooCommercePOS\SHORT_NAME;
1415
use WP_REST_Controller;
1516
use WP_REST_Request;
@@ -48,6 +49,24 @@ public function register_routes(): void {
4849
'permission_callback' => '__return_true', // Public endpoint - no authentication required
4950
)
5051
);
52+
53+
// Refresh access token using refresh token
54+
register_rest_route(
55+
$this->namespace,
56+
'/' . $this->rest_base . '/refresh',
57+
array(
58+
'methods' => WP_REST_Server::CREATABLE,
59+
'callback' => array( $this, 'refresh_token' ),
60+
'permission_callback' => '__return_true', // Public endpoint - validates refresh token internally
61+
'args' => array(
62+
'refresh_token' => array(
63+
'description' => __( 'The refresh token to use for generating a new access token.', 'woocommerce-pos' ),
64+
'type' => 'string',
65+
'required' => true,
66+
),
67+
),
68+
)
69+
);
5170
}
5271

5372

@@ -106,4 +125,62 @@ public function test_authorization( WP_REST_Request $request ): WP_REST_Response
106125

107126
return rest_ensure_response( $response_data );
108127
}
128+
129+
/**
130+
* Refresh access token using a valid refresh token.
131+
*
132+
* This endpoint allows clients to obtain a new access token using a valid refresh token.
133+
* Compatible with the axios-auth-refresh library and follows OAuth 2.0 refresh token flow.
134+
*
135+
* @param WP_REST_Request $request The REST request object.
136+
*
137+
* @return WP_REST_Response
138+
*/
139+
public function refresh_token( WP_REST_Request $request ): WP_REST_Response {
140+
$refresh_token = $request->get_param( 'refresh_token' );
141+
142+
if ( empty( $refresh_token ) ) {
143+
return rest_ensure_response( array(
144+
'error' => 'invalid_request',
145+
'error_description' => 'Missing refresh_token parameter',
146+
), 400 );
147+
}
148+
149+
$auth_service = AuthService::instance();
150+
$result = $auth_service->refresh_access_token( $refresh_token );
151+
152+
if ( is_wp_error( $result ) ) {
153+
$error_code = $result->get_error_code();
154+
$error_msg = $result->get_error_message();
155+
$status = $result->get_error_data()['status'] ?? 400;
156+
157+
// Map error codes to OAuth 2.0 standard error responses
158+
$oauth_error = 'invalid_grant'; // Default OAuth error for refresh token issues
159+
160+
if ( false !== strpos( $error_code, 'invalid_token' ) || false !== strpos( $error_code, 'revoked' ) ) {
161+
$oauth_error = 'invalid_grant';
162+
} elseif ( false !== strpos( $error_code, 'user_not_found' ) ) {
163+
$oauth_error = 'invalid_grant';
164+
}
165+
166+
return rest_ensure_response( array(
167+
'error' => $oauth_error,
168+
'error_description' => $error_msg,
169+
), $status );
170+
}
171+
172+
// Calculate expires_in for axios-auth-refresh compatibility
173+
$current_time = time();
174+
$expires_in = max( 0, $result['expires_at'] - $current_time );
175+
176+
// Return response in format compatible with axios-auth-refresh
177+
$response_data = array(
178+
'access_token' => $result['access_token'],
179+
'token_type' => $result['token_type'],
180+
'expires_in' => $expires_in,
181+
'expires_at' => $result['expires_at'],
182+
);
183+
184+
return rest_ensure_response( $response_data );
185+
}
109186
}

0 commit comments

Comments
 (0)