Orkun Posted February 25, 2020 Share Posted February 25, 2020 Hi Guys We are trying to build a Login Mask (with Node.js) which should act as a single sign on for two websites. The first website is a angular project on firebase the other one is processwire. We are trying to achieve the project with JWTs (Json Web Tokens). My Question is how can I make a user be loggedin in processwire with a JWT? Has someone experiences with this? Link to comment Share on other sites More sharing options...
dragan Posted February 25, 2020 Share Posted February 25, 2020 Here's an example with JWT + Vue. 1 Link to comment Share on other sites More sharing options...
Craig Posted February 25, 2020 Share Posted February 25, 2020 (edited) Hi Orkun! I use the Firebase PHP JWT library when I need to use JWTs, and I would do it like this with PW: use \Firebase\JWT\JWT; // http://example.com/sso/?token=eyJhbGciOiJIUzI... $token = wire('input')->get('token'); // If not token, show error? $key = 'ABC123'; // Store/load your key somewhere (e.g. PW's $config var) try { $decoded = JWT::decode($token, $key, array('HS256')); } catch (\Exception $e) { // Error parsing/decoding token - do not accept. Show error/redirect. } // print_r($decoded); // Find user based on supplied email. // Use other PW user fields or properties from JWT as necessary. $u = wire('users')->get('email=' . wire('sanitizer')->selectorValue($decoded->email)); if ( ! $u->id) { // Could not find user - don't exist. // Could create them at this point, if you have enough detail in the JWT to do so. } // Force user login wire('session')->forceLogin($u); // Go to another page (don't stay on this one) wire('session')->redirect('/'); Edited February 25, 2020 by Craig A Rodway Added post-login redirect 3 Link to comment Share on other sites More sharing options...
Orkun Posted February 25, 2020 Author Share Posted February 25, 2020 28 minutes ago, Craig A Rodway said: Hi Orkun! I use the Firebase PHP JWT library when I need to use JWTs, and I would do it like this with PW: use \Firebase\JWT\JWT; // http://example.com/sso/?token=eyJhbGciOiJIUzI... $token = wire('input')->get('token'); // If not token, show error? $key = 'ABC123'; // Store/load your key somewhere (e.g. PW's $config var) try { $decoded = JWT::decode($token, $key, array('HS256')); } catch (\Exception $e) { // Error parsing/decoding token - do not accept. Show error/redirect. } // print_r($decoded); // Find user based on supplied email. // Use other PW user fields or properties from JWT as necessary. $u = wire('users')->get('email=' . wire('sanitizer')->selectorValue($decoded->email)); if ( ! $u->id) { // Could not find user - don't exist. // Could create them at this point, if you have enough detail in the JWT to do so. } // Force user login wire('session')->forceLogin($u); Hi @Craig A Rodway Thank you very much! I tested it and it works great. One question though, where would you place the code above? I placed it for the moment inside the _init.php because it is prepend for every template. KR Orkun Link to comment Share on other sites More sharing options...
Craig Posted February 25, 2020 Share Posted February 25, 2020 Great! The best location will depend on your circumstances and how you're directing unauthenticated users to the site. I typically create a single SSO endpoint - like /sso/. In PW land this would be an 'sso' template with the template file contents having the above code, then a page named 'sso' using that template. Then you can point people to example.com/sso/?token=eyJhbGciOiJIUzI... and have the generated token in the query string. It will log them in, and then you can redirect them to the homepage, or other desired content. If you're not pointing people to a specific SSO page - and instead just directing them to the site with the token in the query string - you definitely want to catch this as soon as possible. Using the _init.php file prepended to every template is one of several good places to put it, but you could also create a hook (like in site/init.php or site/ready.php) as well, but not sure (without testing) which methods I'd want to hook. Using either of those approaches, I'd also wrap the code in a function you can call from them to keep it tidy and/or reusable - check for the token - if present, validate and log them in; if not - just do nothing. Link to comment Share on other sites More sharing options...
Orkun Posted February 25, 2020 Author Share Posted February 25, 2020 1 hour ago, Craig A Rodway said: Great! The best location will depend on your circumstances and how you're directing unauthenticated users to the site. I typically create a single SSO endpoint - like /sso/. In PW land this would be an 'sso' template with the template file contents having the above code, then a page named 'sso' using that template. Then you can point people to example.com/sso/?token=eyJhbGciOiJIUzI... and have the generated token in the query string. It will log them in, and then you can redirect them to the homepage, or other desired content. If you're not pointing people to a specific SSO page - and instead just directing them to the site with the token in the query string - you definitely want to catch this as soon as possible. Using the _init.php file prepended to every template is one of several good places to put it, but you could also create a hook (like in site/init.php or site/ready.php) as well, but not sure (without testing) which methods I'd want to hook. Using either of those approaches, I'd also wrap the code in a function you can call from them to keep it tidy and/or reusable - check for the token - if present, validate and log them in; if not - just do nothing. Hi @Craig A Rodway Ok thank you very much! I have made now a function called ssoLogin() and place the hook inside /site/ready.php: function ssoLogin() { if(!wire('user')->isLoggedin()) { $token = wire('input')->get('token'); // If not token, show error? try { $decoded = JWT::decode($token, wire('modules')->RestApi->jwtSecret, array('HS256')); } catch (\Exception $e) { // Error parsing/decoding token - do not accept. Show error/redirect. } // print_r($decoded); // Find user based on supplied email. // Use other PW user fields or properties from JWT as necessary. $u = wire('users')->get('email=' . wire('sanitizer')->selectorValue($decoded->claims->email)); if ( ! $u->id) { // Could not find user - don't exist. // Could create them at this point, if you have enough detail in the JWT to do so. } // Force user login return wire('session')->forceLogin($u); } return false; } // Inside /site/ready.php $this->addHookAfter('PageRender::renderPage', function(HookEvent $event) { if (strpos($_SERVER['REQUEST_URI'], $this->wire('config')->urls->admin) === 0 || $this->wire('page')->template->name == 'admin') return; ssoLogin(); }); KR Orkun Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now