Skip to content

Add support for OAuth 2.0 Device Authorization Grant #11063

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

Open
yogeshVU opened this issue Apr 5, 2022 · 14 comments
Open

Add support for OAuth 2.0 Device Authorization Grant #11063

yogeshVU opened this issue Apr 5, 2022 · 14 comments
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement

Comments

@yogeshVU
Copy link

yogeshVU commented Apr 5, 2022

We should consider adding support for OAuth 2.0 Device Authorization Grant.

@yogeshVU yogeshVU added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Apr 5, 2022
@jgrandja jgrandja changed the title Support for Device Code Flow in Oauth2 Add support for OAuth 2.0 Device Authorization Grant Apr 8, 2022
@jgrandja jgrandja added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) and removed status: waiting-for-triage An issue we've not yet triaged labels Apr 8, 2022
@jgrandja jgrandja removed their assignment Apr 8, 2022
@Enkosz
Copy link
Contributor

Enkosz commented Jun 27, 2022

Hi! I would like to work on this one this summer if is possible

@sjohnr sjohnr self-assigned this May 25, 2023
franticticktick pushed a commit to franticticktick/spring-security that referenced this issue Mar 28, 2024
franticticktick pushed a commit to franticticktick/spring-security that referenced this issue Mar 28, 2024
franticticktick pushed a commit to franticticktick/spring-security that referenced this issue Mar 28, 2024
franticticktick pushed a commit to franticticktick/spring-security that referenced this issue Mar 28, 2024
@franticticktick
Copy link
Contributor

I have added DeviceCodeOAuth2AuthorizedClientProvider. The OAuth2AuthorizationContext should be based on the response from the device authorization endpoint. I haven't added it to OAuth2AuthorizedClientProviderBuilder and DefaultOAuth2AuthorizedClientManager yet. I'm not sure yet how suitable this solution is.

@sjohnr
Copy link
Contributor

sjohnr commented Mar 28, 2024

@CrazyParanoid thanks for wanting to work on this! Please note that it's best to discuss an issue and have it assigned first before working on it. Have you seen the sample code in Spring Authorization Server for this?

I have discussed this issue with @jgrandja in the past and while we haven't ruled out providing support in Spring Security for this (this issue), there is not any evidence that Spring Security requires client-side support. The reason for this is that it seems likely many device grant clients will be public clients implemented in native apps (e.g. tvOS, Android TV, etc.) and not written in Java or running on Spring powered backends. Do you have a use case for a device grant client that uses Spring Security? If so, can you please share some information about it?

@franticticktick
Copy link
Contributor

Hi @sjohnr, thanks for you feedback! I can describe the implementation of device code flow on BFF, which I am implementing in my project. To implement such an architecture, I need a bff gateway, for example, spring cloud gateway. To start authentication, I implemented the request:

    @PostMapping("/auth")
    public void authenticate(@RequestBody AuthRequest request) {
        OAuth2DeviceAuthorizationResponse response = oAuth2VerificationProvider.verify(OAuth2VerificationRequest.from(clientRegistration));
        smsService.sendSms(new SmsRequest(request.getPhone(), response.getVerificationUriComplete()));
    }

I have my custom OAuth2VerificationProvider component:

public interface OAuth2VerificationProvider {

    OAuth2DeviceAuthorizationResponse verify(OAuth2VerificationRequest request);

}

With implementation:

public class DeviceCodeOAuth2VerificationProvider implements OAuth2VerificationProvider {

    private final OAuth2VerificationWebClient<OAuth2VerificationRequest> deviceCodeOAuth2VerificationWebClient = new DeviceCodeOAuth2VerificationWebClient();
    private final PollingOAuth2AuthorizedClientManager auth2AuthorizedClientManager = new PollingOAuth2AuthorizedClientManager();

    @Override
    public OAuth2DeviceAuthorizationResponse verify(OAuth2VerificationRequest request) {
        OAuth2DeviceAuthorizationResponse authorizationResponse = deviceCodeOAuth2VerificationWebClient.getOAuth2VerificationResponse(request);
        auth2AuthorizedClientManager.setPollingAuthenticationTask(
                new AuthenticationTask(authorizationResponse.getDeviceCode(),
                        authorizationResponse.getInterval())
        );

        return authorizationResponse;
    }
}

This component first receives a response from the IDP, after which the IDP polling process will be started to obtain the token. PollingOAuth2AuthorizedClientManager delegates a request to DefaultOAuth2AuthorizedClientManager on a schedule with settings received from deviceCodeOAuth2VerificationWebClient. DefaultOAuth2AuthorizedClientManager must support DeviceCodeOAuth2AuthorizedClientProvider.
I send SMS to user with verificationUriComplete. After receiving authentication, routes with TokenRelay start working.

@sjohnr
Copy link
Contributor

sjohnr commented Mar 29, 2024

Hi @CrazyParanoid, thanks for providing those details.

Generally, device code provides an OAuth2 flow for devices that are input constrained, meaning there's no keyboard or it is not convenient to present one to the user for traditional authentication and consent for authorization. Based on the code you have provided, it seems possible you are implementing an out-of-band authentication mechanism (similar to an MFA second factor) on top of device code, which is not exactly what device code is intended for. Also, I feel that providing a phone number as a means for initiating the authorization flow on another device is not in keeping with the intent of the device grant specification, which states:

5.7. Non-Visual Code Transmission

There is no requirement that the user code be displayed by the device
visually. Other methods of one-way communication can potentially be
used, such as text-to-speech audio or Bluetooth Low Energy. To
mitigate an attack in which a malicious user can bootstrap their
credentials on a device not in their control, it is RECOMMENDED that
any chosen communication channel only be accessible by people in
close proximity, for example, users who can see or hear the device.

Can you describe why you are not using the authorization code grant for your use case? Am I correct that you're trying to design an out-of-band authentication flow? Or are requests to this BFF actually coming from an input-constrained device?

@franticticktick
Copy link
Contributor

franticticktick commented Mar 29, 2024

In my case, I have an embedded system with an operating system with very limited functionality. There are quite a lot of such embedded systems and there is no way to implement traditional browser flow, for example, authorization code grant.
As you correctly noted:

There is no requirement that the user code be displayed by the device visually.

From which I conclude that sending verification_uri_complete does not contradict the specification, but it is quite possible that I am very mistaken.

Also, I feel that providing a phone number as a means for initiating the authorization flow on another device is not in keeping with the intent of the device grant specification

Most likely you are right, the goal of my architecture was to achieve the implementation of device code flow through BFF, which carries certain benefits. This has led to some compromises, but that's just my opinion.
I didn't know that device code grant support is not planned in spring security, sorry for the premature PR.

@sjohnr
Copy link
Contributor

sjohnr commented Apr 1, 2024

Thanks for the additional details, @CrazyParanoid. I think it's important for cases like this to identify one or two solid use cases to understand how this support might be used before committing to including it (if there's a question about whether it should be included, which there is in this case).

I didn't know that device code grant support is not planned in spring security, sorry for the premature PR.

Please don't worry about that, I am glad you are interested in providing it. Having the conversation first is helpful though. It's not that support isn't planned, only that we are unsure whether it will be useful and worth providing. I'll discuss this with @jgrandja in the next week or so and get back to you on whether your use case provides a good incentive for including it.

@sjohnr
Copy link
Contributor

sjohnr commented Apr 4, 2024

@CrazyParanoid as you may know, we generally prioritize features based on community upvotes on issues. Currently, this issue only has one upvote (👍) after being opened over a year, which seems to suggest there is very low demand for this support in Spring Security. After discussing this internally, we feel like it would be worth waiting to provide client support for OAuth 2.0 Device Authorization Grant once there is more community demand for the feature, so we will not proceed to the PR stage at this time. If anyone in the community has need for this support in Spring Security, I'd encourage them to upvote this issue so that we can prioritize it.

In the meantime, you are of course welcome to re-use the classes from implementation you provided in the PR (gh-14816) or the classes from the demo client in Spring Authorization Server samples.

@sjohnr sjohnr removed their assignment Apr 4, 2024
@colin-riddell
Copy link

What's the most recent advice on this? We might have a need for device flow support. Kind Thanks

@sjohnr
Copy link
Contributor

sjohnr commented Jul 5, 2024

No updates at this time, @colin-riddell.

If you get to the point where you have a clearly defined need for the device flow in your client, it would be extremely helpful if you could provide some high level details (as mentioned above) of your use case. For example, what client/server arrangement do you have such that you would be able to make use of a device code client in a Spring application (as opposed to a native app client, for example).

@colin-riddell
Copy link

Hi @sjohnr -
This wouldn't be to support a Spring Application based client at all. It's a bare-bones reduced capacity thin client that runs as part of a lightweight application for media/STB. It's got reduced capacity for interaction and computation. Not quite embedded but close.
I understand that that there'd be absolutely no need to support this flow for a client that can run a Spring application.

Maybe I misunderstand; but there's presumably no valid use-case for this kind of flow for a Spring application client?

@sjohnr
Copy link
Contributor

sjohnr commented Jul 5, 2024

Hey @colin-riddell.

This wouldn't be to support a Spring Application based client at all.

Ok. So it sounds like you would only have use for the Spring Authorization Server support (which is already available since the 1.2 release).

Maybe I misunderstand; but there's presumably no valid use-case for this kind of flow for a Spring application client?

I think there probably are valid use cases, it's just that I don't have a clear idea of what those use cases are so we need folks in the community to outline one or more of them for us so we can decide if it's truly useful to add support to the framework. Certainly, I think there are fewer good use cases for device code grant in a Spring application client than for other grant types (such as the ones already supported).

@colin-riddell
Copy link

Hey @sjohnr

Ah ok I didn't realise that Authorization Server supported it already. It wasn't clear to me. I apologize.
Kind thanks

@Kehrlann
Copy link
Contributor

I've had an interesting use-case for device-code grant: CLI apps that do not wish to (or cannot) open an ephemeral port.

When I build a Spring Shell app, and I want to avoid running a full web-server inside that app, it is much easier to go through the device_code grant rather than try and fine-tune the app to open a small web server and close it after a token has been obtained.

It is also useful in scenarios where loopback redirects are painful, e.g. when working over SSH where tunneling on ephemeral is extremely unwieldy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants