thephpleague / oauth2-server

A spec compliant, secure by default PHP OAuth 2.0 Server
https://oauth2.thephpleague.com
MIT License
6.51k stars 1.12k forks source link

Straight way to issue access token #1245

Closed ybelenko closed 2 years ago

ybelenko commented 3 years ago

Sometimes I need to create short living access token without direct user request. Most obvious example is mail with token after some server event.

I know, that's against recommendations and best practises to include access token in url, but 99% of web applications send reset password link with token in it. Cannot see any difference if I send reset link with access token.

So, it would be great to have a way to call issueAccessToken directly from AuthorizationServer instance, not from grant(it's impossible since method is protected).

I already wrote some workaround to achieve that, but official feature covered with tests sounds much more promising.

Sephster commented 2 years ago

Apologies for my delay in responding to this. The reason the access token is not usually sent in the url is because it is much more vulnerable to interception.

The library will only ever support the official OAuth standards and your proposal would counter that so it is not something we would be willing to look at at this time. I'm sorry that this likely isn't the answer you were looking for but I hope you understand our reasoning. Thanks for reaching out.

ybelenko commented 2 years ago

@Sephster thanks for your answer. I understand, email confirmation is far away from OAuth standard. No hard feelings since I've already implemented it in a custom grant.

If anyone needs the same feature - drop a comment in this issue and I can share it via fork or a Gist.

delboy1978uk commented 1 year ago

@ybelenko I have a native app with auth code flow working perfectly. for user registration, I send an account activation link email, which opens back up in the app and makes an API call to my server confirming the email. At that point, I want to issue an access token too. It works, but for some reason my refresh token isn't decrypting properly, I'm still working on that, but I'd be very interested to see your custom grant type!

ybelenko commented 1 year ago

@ybelenko I have a native app with auth code flow working perfectly. for user registration, I send an account activation link email, which opens back up in the app and makes an API call to my server confirming the email. At that point, I want to issue an access token too. It works, but for some reason my refresh token isn't decrypting properly, I'm still working on that, but I'd be very interested to see your custom grant type!

My current custom grant sends generated access token to user email as url query or path parameter:

http://app.dev/?token={{jwtAccessToken}}

Do you also need refresh token sent via mail? Makes no sense to me at the moment, because regarding to email activation - token should work as one time password, then it's better be access token(without refresh token) with a short live period. Then user have to signin again. The same for password reset process.

I agree that there are different cases. For instance when server needs to generate activation links from a scheduled job(Cron) then it doesn't have http request to respond to, so something like custom_cli_grant required to issue tokens for any user without actual user action. I faced that problem last year when developed project with high security requirements. One of the requirement was to force user reset his password each 3 months, then you need option to generate thousands of links with encoded access token from single php script execution.

delboy1978uk commented 1 year ago

thanks for your feedback @ybelenko, I solved my issue the other day. When I click the email link, it opens the app, and then sends the email verification code to the api, and when successful I just create a new auth code request and pass it directly into my auth server controller, then an access token request, meaning i don't have to do anything different or custom :-D So no access token or refresh token is anywhere near the email or the frontend app

ybelenko commented 1 year ago

Here is my custom implementation ybelenko/oauth2_email_grant. It accepts two callbacks, first executed on success access token creation, second optional callback performs extra email validation.

User repository method should be aware of new custom grant like:

final class FakeUserRepository implements UserRepositoryInterface
{
    /**
     * {@inheritdoc}
     */
    public function getUserEntityByUserCredentials(
        $username,
        $password,
        $grantType,
        ClientEntityInterface $clientEntity
    ) {
        if ($grantType === 'custom_email') {
            // then username is email and password is empty string('')
            // find related user and return it
            $user = new FakeUserEntity();
            $user->setIdentifier($username);
            return $user;
        }

        return null;
    }
}
delboy1978uk commented 1 year ago

Thanks for sharing! :-D

ybelenko commented 1 year ago

When I click the email link, it opens the app, and then sends the email verification code to the api

Well, it seems like you generate that verification code by yourself. That's an option, but for me the biggest advantage of OAuth2 framework is strict token generation process, so I wanna use it as much as possible and don't reinvent my own authorization wheels. I would even send it as sms one time password for phone verification, but it's obviously too big for that purpose. 🤣 With OAuth2 + JWT I can forget about sessions(cookies) and can avoid storing short lived access tokens(OTPs for user phone/email verifications, sometimes even API keys) in database.