Introduction
Hi, my name is Onwuesi Williams Chukwuemeka. I am a PHP/Laravel developer.
First of all, I want to say a big thank you to 1Password and Hashnode for providing this opportunity for developers to learn, explore their creativity, and have an opportunity to earn in the process.
A Brief Overview of Passage
Before we begin the integration process properly, let us briefly get acquainted with Passage and how it can be integrated into your application/website. Passage is an authentication system that allows your users to securely sign into your website/web application without a password. Sounds great right? Too good to be true. Passage also eradicates some issues that traditional web applications face like forgotten passwords, email verification, and always entering passwords when logging in to a user account.
Bringing the power of passage to Laravel
This package was created to demonstrate the implementation of Passage Passwordless authentication backend enforcement in a Laravel framework. Thereby creating a user for every registered passage user or logging in an already created passage user and creating a session for the currently logged-in user. Passage also verifies the user's email so you can be sure that the email you receive from Passage has already been verified.
This project is located here on GitHub.
This project was implemented with
Passage Template Tags
A passage middleware that checks if a user exists using the sub claim of the parsed passage JWT. if the user exists, the user is logged in and the user's session is regenerated. the user can then navigate all protected routes all an authenticated user would normally do. if the user does not exist, the middleware creates a new user with the sub claims and logs in the newly created user. If there is an error in the registration process, the middleware throws an error.
A migration that modifies the Users table and adds Passage enabling modifications to the Users table.
A controller that redirects the successfully authenticated or registered user to their profile. where they can also edit their details desired.
we would need to install a PHP JWT parser package using Composer. (One recommended by Passage is lccobucci JWT).
Passage Integration Process Proper
Step 1 - Go to https://passage.1password.com and click the sign-up button to sign up. If you have signed up already, click the login button to log in. You would be presented with Passage passwordless authentication system. follow the prompts to complete the login or sign-up step.
Step 2 - When logged into your account click the Create New App button, and fill in the form accurately as instructed, this includes filling in an App name, an Origin URL and a redirect URL. Follow the prompts to create a new app.
Step 3 - Use the app_id to create the passage login element on your login page. As demonstrated below
Step 4 - when login or registration is successful we want to enforce the authentication in our backend. To do so you either have to work with an SDK or do it manually. I would be enforcing manually as no SDK or package is provided for my framework at the moment.
Hence we want to catch the psg_auth_token cookie sent to our stipulated redirect route. This is a JWT(JSON Web Token) returned to our client as a cookie by passage after successful authentication (Login or registration). We would need to parse this token with a JWT parser to access the claims. For this Passage recommends Lccobucci JWT for PHP servers. I am working with a PHP framework(Laravel) so that is what I would be working with. After parsing the token and getting the sub claim, so I used the sub claim as an id to log in a user or create a user.
If the sub claim value does not exist as an id in the database. If the id exists the user is logged in and if the id does not exist, a new user I created with that id. The user is then logged into the normal session and can access every authenticated route as normal.
5 - The raw passage SDK is also used to create a register/enable passkey functionality for already existing legacy authentication users. This would allow them to enable Passage passwordless authentication functionality anytime they want. instead of forcing all your users to migrate to the passwordless authentication method all at once, they can slowly transition into the passwordless authentication system gradually.
Click here to see the official Passage documentation.
Integrating Passage Passwordless Authentication Feature With My Website
This package was created following these steps
1 - A Get route ("/passwordless_login") is created to return a passwordless_auth view. The passage element would be placed in this view, after successful authentication, the user is redirected to a redirect route set in your passage application. This redirect route would be implemented in the second step
2 - A Get Redirect route is implemented, this is where the user would be redirected after successful authentication by Passage.
3 - A middleware is created and set to run before the user is allowed to access the redirect route. This middleware checks for a cookie with the key psg_auth_token. If this cookie is available, it parses the cookie value using a JWT parser. The JWT parser recommended by Passage for PHP applications is lcobucci/jwt. This JWT parser parses the psg_auth_token JWT token and extracts the claims. The sub claim contains a unique id for the authenticated user. This id can be used to get more details about the authenticated user like the user's email. See details here These user details and id are used to create a user in the database. In the case of login, the server checks to see if a user exists in the database with the parsed psg_auth_token sub claim(id). If the user exists, the server logs in that user. In this case, we are using Laravel so we get the user id with the sub id and use it to log in the authenticated user as shown below.
/* ---------------------------------------------- */
/* Getting JWT Claims from the parsed Passage JWT */
/* ---------------------------------------------- */
$passage_auth_token = $token->claims()->get('sub');
$user_key = User::where('psg_auth_token_sub', $passage_auth_token)->value('id');
/* -------------------------------------- */
/* Attempt to Login Passage JWT sub claim */
/* -------------------------------------- */
if (Auth::loginUsingId($user_key)){
$request->session()->regenerate();
return $next($request);
}
4 - A migration is created to modify the users table and add passage enabling changes to the table (to add a nullable "psg_auth_token_sub" column. The column is set to nullable as a user is expected to be able to exist without a psg_auth_token_sub(id). "The Legacy auth Users"). The psg_auth_token_sub column would be used to store the parsed psg_auth_token sub value. This package also allows existing Legacy authentication users to enable passwordless authentication on their account whenever they please providing flexibility in authentication for your web application/website. This can be done in the user's profile.
5 - A Get route "/enable_auth" is created to return an enable_passwordless_auth view page. A button is created to trigger the registration process. Once the button Enable Passwordless Auth is clicked, the view gets the authenticated user's email and uses it as an identifier to initiate a Passage Passwordless Authentication registration process for the authenticated user. If the registration is successful, the user is prompted to Login using the passwordless authentication modal to confirm enablement success.
Running The Project
To run this project, you need to follow the steps below
1 - clone the Github repository,
2 - In your terminal, cd into the project directory and run composer install
3 - Then run php artisan key:generate
This would generate a key for your laravel application
4 - Run php artisan migrate
to migrate tables to your database. The default database is laravel, but you can update this value in your env file as well.
5 - Set PASSAGE_APP_ID env variable to a passage app_id. This app_id would be used to create a passage Element in your frontend and more as stated above.
6 - Lastly, run php artisan serve
A server would be created for you at loocalhost:8000, you can then visit this link in your browser to check out the project.
Conclusion
Once again I want to say a very big Thank You to 1Password and Hashnode for this great opportunity to explore my creativity and learn. I learned a lot in the process.
Thank you for your time, I hope you enjoyed the article.
Until next time. Bye for now.๐