Open corsacca opened 8 months ago
Here is a ref to the Auth0 docs:
OAuth2 has a similar flow:
For our purposes, since we also want to support a refresh_token
, then we could probably just use the same endpoint (and grant_type=refresh_token
):
https://developer.okta.com/docs/reference/api/oidc/#token
So, when that endpoint is accessed with that grant_type, then we check for the refresh token in the request. If it is present and valid, then issue new JWT (access and refresh tokens). If not (here is where the cookie exchange comes into play), we could validate the cookie, and assuming it is valid, then we also return a new JWT (access and refresh tokens), but this time via a more secure redirect that only the app will be handling. Then from that point forward, the mobile app will attempt to refresh the tokens according to the normal flow mentioned above (to keep the user logged in for as long as they actively use the app).
THanks @zdmc23
would the refresh_token be able to happen in the background, so the user would not experience the redirects?
THanks @zdmc23
would the refresh_token be able to happen in the background, so the user would not experience the redirects?
@corsacca Yes, with each API request, we could check the expiration date of the token, and just refresh it when it is getting close to expire. The user never notices anything different. Linking it to the usage is desirable, bc most often we do want the token to expire when they haven't been actively using the app/API (for security sake, so they haven't simply lost their phone or a hostile family member starts randomly checking apps, etc...)
@corsacca I think we can make this work without many changes. It relies on the redirect_to
parameter at login:
https://example.com/wp-login.php?redirect_to=/wp-json/jwt-auth/v1/token
Upon successful login (whether standard username/password, MFA, SSO, whichever plugins are being used, so long as the standard WordPress redirect_to
is being honored), it will redirect to the new endpoint which exchanges a valid session (ie, cookie) for a JWT access token.
Here is the code snippet to make it happen:
All edits would be in: https://github.com/DiscipleTools/disciple-tools-theme/blob/develop/dt-core/libraries/wp-api-jwt-auth/public/class-jwt-auth-public.php
/**
* Add the endpoints to the API
*/
public function add_api_routes() {
register_rest_route( $this->namespace, 'token', [
'methods' => 'GET',
'callback' => [ $this, 'exchange_cookie_for_jwt' ],
'permission_callback' => '__return_true',
] );
register_rest_route( $this->namespace, 'token', [
'methods' => 'POST',
'callback' => [ $this, 'generate_token' ],
'permission_callback' => '__return_true',
] );
register_rest_route( $this->namespace, 'token/refresh', [
'methods' => 'POST',
'callback' => [ $this, 'refresh_access_token' ],
'permission_callback' => '__return_true'
]
);
register_rest_route( $this->namespace, 'token/validate', [
'methods' => 'POST',
'callback' => [ $this, 'validate_token' ],
'permission_callback' => '__return_true',
] );
}
public function refresh_access_token(WP_REST_Request $request) {
if ( !$this->has_permission() ) {
return new WP_Error( __FUNCTION__, "You do not have permission for this", [ 'status' => 403 ] );
}
$this->validate_token( $request );
$token = $this->generate_token_static( 'dummy-email', 'dummy-password' );
//remove_filter( 'authenticate', [ $this, 'allow_programmatic_login' ], 10 );
if ( $token ) {
return [
'login_method' => DT_Login_Methods::MOBILE,
'jwt' => $token,
];
}
}
public function exchange_cookie_for_jwt(WP_REST_Request $request) {
//if ( !is_user_logged_in() ) {
if ( !wp_validate_auth_cookie() ) {
wp_redirect( '/wp-login.php' );
exit();
}
$token = $this->generate_token_static( 'dummy-email', 'dummy-password' );
wp_redirect( 'exp://127.0.0.1:8081/?token=' . $token );
//wp_redirect( 'discipletools://example.com/?token=' . $token );
//wp_redirect( 'dt://example.com/?token=' . $token );
exit();
}
A couple of notes:
the Redirect URI for the App probably needs to be configurable (not sure whether you have any preferences on where that belongs):
exp://127.0.0.1:8081
. dt://example.com/
(more obscure for security sake, but also greater chance of collision with other Apps since only 2 letter protocol), or discipletools://example.com
(whichever you prefer that we use)redirect_to
since it is a WP standard)currently generate_token
requires email and password, but it probably shouldn't. That's not required for a JWT token. So we either need to change that, or update the code above to pull the User email and credentials and then pass them so the JWT token can be generated on "refresh"
feel free to refactor the above however it should be to fit the D.T standard. In some sense it is pseudocode, bc I needed to comment out things like (bc it did not work to validate the cookie like I expected, etc...):
if ( !wp_validate_auth_cookie() ) {
wp_redirect( '/wp-login.php' );
exit();
}
Thx!
Some other related things to eventually discuss, but not urgent:
{
"access_token" : "ey...onNtiw",
"token_type" : "Bearer",
"expires_in" : 3600,
"scope" : "openid email",
"refresh_token" : "ey...kk2VdY",
"id_token" : "ey...kpOurg"
}
^ sorry, I realized the prev video did not show the actual WP login form flow (bc of a prev login attempt caching the cookie into the ios jar), but here is an example that also includes MFA with TOTP. It works nicely
Hey @zdmc23,
I had a go at implementing the cookie exchange and refresh endpoints using your code above.
See https://github.com/DiscipleTools/disciple-tools-theme/pull/2586
you can try the GET wp-json/jwt-auth/v1/token
and POST wp-json/jwt-auth/v1/token/refresh
@kodinkat implemented some auto refresh strategy: https://github.com/DiscipleTools/disciple-tools-theme/pull/2548
I'm looking for what the mvp would be to get this working.
Signing in from the website will be helpful in any app or external server.
I need to double check how our SSO strategy could workflow works with this too.
@corsacca Thx! What is the best way to download the theme for this particular commit hash? I can test it locally with my previous tester mobile app to try to confirm it
Most efficient? Checkout the auth-redirect branch of the theme. otherwise direct download: https://github.com/DiscipleTools/disciple-tools-theme/archive/refs/heads/auth-redirect.zip
Here is an example of ChatGPT using Auth0 for a web browser based mobile login flow:
https://github.com/DiscipleTools/disciple-tools-theme/assets/191707/74a70def-5382-4f89-bd42-01c0720fdeb1