Skip to content
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

Bearer token auth #43

Closed
wants to merge 2 commits into from
Closed

Conversation

jjjrmy
Copy link

@jjjrmy jjjrmy commented Mar 2, 2024

One thing I'm not sure how to do ...
For CapacitorJS, it doesn't seem to find the modules when they are only installed from inside the package.
Probably there is a way to fix that, I'm just not sure how.

In order to use this for now you also need to install the dependencies locally and use npx cap sync

To use this you also need to make an endpoint for Mobile Login & Logout

Route::post('/login/mobile', function (\App\Http\Requests\Auth\LoginRequest $request) {
    $request->authenticate();
    $token = $request->user()->createToken(now()->toDateString())->plainTextToken;
    return Response::json(['token' => $token]);
}) ->middleware('guest')->name('login.mobile');

Route::post('/logout/mobile', function (\Illuminate\Http\Request $request) {
    $request->user()->currentAccessToken()->delete();
    return Response::json([]);
})->middleware('auth:sanctum')->name('logout.mobile');

@jjjrmy
Copy link
Author

jjjrmy commented Mar 2, 2024

@manchenkoff
Maybe we can get rid of Capacitor.isNativePlatform() and leave that as an option when you are building?
Since I imagine you wouldn't build your Mobile and Web version releases at the same time?

So instead you just set your build environment and in your config switch the login/logout urls there.

What do you advise? I think no matter what we need to use the Capacitor Preferences to store the data or we can try local storage?

It all depends how we want this to function. If we want Token Authorization available for non-mobile devices. Your input is appreciated

@manchenkoff
Copy link
Owner

Hey @jjjrmy, thanks for the proposal! However, this implementation adds additional dependency that is irrelevant to web projects. Because this module is supposed to provide easy functionality for the web-first projects preferably with zero external dependencies, I suggest removing Capacitor, especially because it is not a universal framework, like Vue and React.

That is how I see the implementation - the only difference between the current implementation and token-based authentication is reading from a response instead of a cookie and building a different request header, so we can introduce a mode configuration parameter with enum values to choose what way of authentication we should apply. Endpoint URLs also could be used as it is, maybe with just a new one for token retrieval instead of csrf to not break backward compatibility, like this:

endpoints: {
    csrf: '/sanctum/csrf-cookie',
    token: '/sanctum/token',
    login: '/login', // could be reused for mobile since one application should not by used for both web and mobile as you mentioned
    logout: '/logout',
    user: '/api/user',
},

As for token storage, since we have no secure storage in web-based applications, I would go with an in-memory state that persists until a page is completely refreshed. LocalStorage doesn't look very secure, but in the case of mobile devices, I believe we can come up with a configurable storage handler that could be provided based on the current project as a function. Not sure if it is possible to implement with the current Nuxt capabilities, but it would give much more flexibility to the end user without a need for the introduction of many dependencies in this module.

P.S.
Since we have several requests for this feature already, I'm going to find some time next week to implement it to support both token- and cookie-based authentication.

@jjjrmy
Copy link
Author

jjjrmy commented Mar 2, 2024

I agree about the dependencies, and also like I said there is a problem with the main Capacitor project actually recognizing the plugins within this package.

we can introduce a mode configuration parameter with enum values to choose what way of authentication we should apply

So in this case we would change the login/logout functionality based on this parameter?
Cookie: same as now, using endpoints.login and endpoints.logout
Bearer: posts to endpoints.token to login and deletes to endpoints.token to logout

I think a decision has to be made on wether we'd reuse the login/logout endpoints for mobile and the user would switch them at compile time based on the build target. The Laravel Sanctum docs suggest /sanctum/token as the endpoint when issuing API tokens, but they are not specific about how you implement the logout endpoint.

As for token storage, since we have no secure storage in web-based applications, I would go with an in-memory state that persists until a page is completely refreshed... I believe we can come up with a configurable storage handler that could be provided based on the current project as a function.

If we are only using in-memory state, then the user will have to login every time they reload the browser or app. That works for default functionality, but if we could set function callbacks within our Nuxt config for the set/get/remove storage methods then someone could use Capacitor as a dependency if required.

@manchenkoff
Copy link
Owner

So in this case we would change the login/logout functionality based on this parameter?

Correct

I think a decision has to be made on wether we'd reuse the login/logout endpoints for mobile and the user would switch them at compile time based on the build target.

Yes, the module knows only about the config so it will be the user's responsibility to define proper values based on env/target

If we are only using in-memory state, then the user will have to login every time they reload the browser or app. That works for default functionality, but if we could set function callbacks within our Nuxt config for the set/get/remove storage methods then someone could use Capacitor as a dependency if required.

Yes, I also don't like this approach with an in-memory state, but at the current moment, it is the only idea I have for a cross-platform solution w/o insecure storage 😄 that was the point of cookies, but I will check if there is an option to pass user-defined function handlers

@jjjrmy
Copy link
Author

jjjrmy commented Mar 3, 2024

We don't need to change the login/logout functionality if we just use the same endpoint config.
One thing that might be interesting would be to do the endpoints like this to allow more flexibility.

// for mobile
endpoints: {
    login: '/sanctum/token',
    logout: { url: '/sanctum/token', method: 'DELETE' },
},

@jjjrmy
Copy link
Author

jjjrmy commented Mar 5, 2024

I spent a few hours today on this, I couldn't figure out the best way to pass the callback functions.

I was thinking there is a way to register a composable within the package, and override it on the user's app but I get errors about duplicate imports and it chooses the composable created in the package. Maybe there is a way to set priority or check if the composable is already registered by the user.

It doesn't seem that you can set the functions in Runtime Config, and I wasn't able to figure out how to pass the Module Options into the composables.

Looking at other Nuxt modules, like Formkit, they have their own config file formkit.config.ts and you can for example set a custom iconLoader function if you wanted to. I didn't choose to go this route but it seems the most reliable, there is a bit of work that would need to be done. Let me know your thoughts.

@jjjrmy
Copy link
Author

jjjrmy commented Mar 18, 2024

Closing this in favor of #49

@jjjrmy jjjrmy closed this Mar 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants