question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Device Authorization Grant support

See original GitHub issue

Feature Request

1. Motivation

AppAuth-Android does not currently support authentication for Android devices that either lack a browser or have limited input capabilities to fully perform the traditional authentication flow. Adding support of the extension Device Authorization Grant as described in RFC 8628 would allow such devices to obtain tokens from the authorization server with the help of a secondary device with browser and common input capabilities.

2. Description

As described in Section 1 (RFC 8628), such an implementation would require the addition of a request to perform a device authorization and a polling mechanism for the token request.

2.1 Device authorization

A request such as DeviceAuthorizationRequest could be created with the specifications in Section 3.1 (RFC 8628) and the associated response such as DeviceAuthorizationResponse with the specifications in Section 3.2 (RFC 8628).

To perform this request, an additional endpoint device_authorization_endpoint described in Section 4 (RFC 8628) would have to be added to the AuthorizationServiceDiscovery.

The request would be performed in an AsyncTask such as DeviceAuthorizationRequestTask and would expose the reponse through a callback such as DeviceAuthorizationResponseCallback.

public interface DeviceAuthorizationResponseCallback {

    void onDeviceAuthorizationRequestCompleted(@Nullable DeviceAuthorizationResponse response,
                                               @Nullable AuthorizationException ex);

}

No additional exceptions should be created for this request as the authorization server should respond in the same way as the token endpoint as described in the last paragraph of Section 3.2 (RFC 8628). The choice of an AsyncTask here would be to match the existing implementation of other requests.

To save the new authorization state, AuthState should implement an additional update method to save the last DeviceAuthorizationResponse. The last response will be used to expose parameters such as verification uri, complete verification uri and user code through get accessors as these will be required to perform the authorization request on the secondary device.

The DeviceAuthorizationReponse would also allow for the creation of a TokenRequest in a similar manner that the AuthorizationReponse already does through a member function such as:

public class DeviceAuthorizationReponse {

    public final DeviceAuthorizationRequest request;
    public final String deviceCode;

    public TokenRequest createTokenExchangeRequest() {
        if (deviceCode == null) {
            throw new IllegalStateException("deviceCode not available for exchange request");
        }

        return new TokenRequest.Builder(request.configuration, request.clientId)
            .setGrantType(GrantTypeValues.DEVICE_CODE)
            .setDeviceCode(deviceCode)
            .build();
    }

} 

An additional method should also be provided to allow for the creation of a TokenRequest with non-documented additional parameters.

The TokenRequest would implement the additional parameter deviceCode to allow operations through the extension’s grant type urn:ietf:params:oauth:grant-type:device_code described in the Section 3.4 (RFC 8628).

2.2 Polling mechanism

Right after the application obtained and displayed the information necessary to perform the authorization on a secondary device, it should start polling for an access token associated to the previously obtained deviceCode in the DeviceAuthorizationReponse with the provided TokenRequest.

It would be handy if the AuthorizationService offered an API to perform the polling itself.

class AuthorizationService {

    public void performTokenPollRequest(
            @NonNull TokenRequest request,
            @Nullable Long pollingInterval,
            @NonNull Long expirationTime,
            @NonNull TokenResponseCallback callback)

}

This API would instanciate and execute an AsyncTask such as TokenRequestPollingTask that would inherit from the existing TokenRequestTask. This task would perform the polling loop in its doInBackground method while calling the super class’ doInBackground to execute the provided TokenRequest. The result of this request would be parsed in the loop to interpret the errors described in Section 3.5 (RFC 8628) and decide whether to continue the polling, expand the polling interval, abort due to a critical error or due to the expiration of the device code. A set of additional AuthorizationException described in the extension should also be implemented.

The issue with this approach is the need to have access to the provided polling interval and device code expiration time that are not stored in the TokenRequest. A solution to this would be to provide a helper method in AuthState that would call the AuthorizationService polling method with the parameters provided by the last DeviceAuthorizationReponse.

public class AuthState {

    private DeviceAuthorizationResponse mLastDeviceAuthorizationResponse;

    public void performTokenPollRequest(@NonNull final AuthorizationService service,
                                        @NonNull final ClientAuthentication clientAuth,
                                        @NonNull final AuthorizationService.TokenResponseCallback callback) {
        if (mLastDeviceAuthorizationResponse == null) {
            AuthorizationException ex = AuthorizationException.fromTemplate(
                AuthorizationException.TokenRequestErrors.CLIENT_ERROR,
                new IllegalStateException("No device authorization available for token request"));
            callback.onTokenRequestCompleted(null, ex);
            return;
        }

        service.performTokenPollRequest(mLastDeviceAuthorizationResponse.createTokenExchangeRequest(),
            clientAuth,
            mLastDeviceAuthorizationResponse.tokenPollingIntervalTime,
            mLastDeviceAuthorizationResponse.codeExpirationTime,
            callback);
    }

}

Additional methods should also be provided to allow for the creation of the TokenRequest with non-documented additional parameters and to allow the polling without explicitly providing a ClientAuthentication.

A thead-safe method for canceling the polling request should also be provided.

Upon a successful TokenRequest, the app should update the AuthState with the provided TokenResponse in onTokenRequestCompleted.

3. Alternatives or Workarounds

There is currently no simple way of performing a device authorization.

I already have a draft of the implementation described above, but would love your input on my take. Let me know if you are interested in me providing a merge request.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:14
  • Comments:8

github_iconTop GitHub Comments

1reaction
Healioscommented, Mar 8, 2022

@rodrigoGA I’m using: implementation "com.github.formula-micro:AppAuth-Android:-SNAPSHOT"

1reaction
Healioscommented, Mar 4, 2022

Is there any news about this merge request? Do you plan to add it in the near future?

Not a maintainer, but I wouldn’t expect it to get merged anytime soon. On the “surface” the request seems perfect though, only thing I found was a simple spelling error.

I forked the repository and merged the request back in november (see my fork), and it’s worked really well for me. I’m using my fork via JitPack.

Read more comments on GitHub >

github_iconTop Results From Across the Web

RFC 8628: OAuth 2.0 Device Authorization Grant
The OAuth 2.0 Device Authorization Grant (formerly known as the Device Flow) is an OAuth 2.0 extension that enables devices with no browser...
Read more >
Configure Device Authorization Grant Flow - Okta Developer
The Device Authorization feature is an OAuth 2.0 grant type. It allows users to sign in to input-constrained devices, such as smart TVs,...
Read more >
RFC 8628: OAuth 2.0 Device Authorization Grant - » RFC Editor
RFC 8628 OAuth 2.0 Device Grant August 2019 The device client typically chooses the set of authorization servers to support (i.e., its own...
Read more >
Device Authorization Grant | Curity Identity Server
The Device Authorization Grant, or Device Flow, is very useful for handling authentication and authorization when it is difficult for the user to...
Read more >
OAuth 2.0 device code flow - Microsoft Entra
The Microsoft identity platform supports the device authorization grant, which allows users to sign in to input-constrained devices such as ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found