Skip to content

Commit 2db1db3

Browse files
committed
Update readme with Device Authorization Grant documentation
1 parent cf05011 commit 2db1db3

1 file changed

Lines changed: 128 additions & 2 deletions

File tree

README.md

Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,17 @@ including using
2222
for authorization requests. For this reason,
2323
`WebView` is explicitly *not* supported due to usability and security reasons.
2424

25-
The library also supports the [PKCE](https://tools.ietf.org/html/rfc7636)
25+
The library supports the [PKCE](https://tools.ietf.org/html/rfc7636)
2626
extension to OAuth which was created to secure authorization codes in public
2727
clients when custom URI scheme redirects are used. The library is friendly to
2828
other extensions (standard or otherwise) with the ability to handle additional
2929
parameters in all protocol requests and responses.
3030

31+
The library also offers device flow support as described in
32+
[RFC 8628 - Device Authorization Grant](https://tools.ietf.org/html/rfc8628)
33+
for authenticating devices that either lack a browser or have limited
34+
input capabilities to fully perform the traditional authentication flow.
35+
3136
A talk providing an overview of using the library for enterprise single sign-on (produced by
3237
Google) can be found here:
3338
[Enterprise SSO with Chrome Custom Tabs](https://www.youtube.com/watch?v=DdQTXrk6YTk).
@@ -49,7 +54,9 @@ be used with the library.
4954

5055
In general, AppAuth can work with any Authorization Server (AS) that supports
5156
native apps as documented in [RFC 8252](https://tools.ietf.org/html/rfc8252),
52-
either through custom URI scheme redirects, or App Links.
57+
either through custom URI scheme redirects, or App Links. For the device flow,
58+
the AS would need to properly support the device authorization grant as
59+
documented in [RFC 8628](https://tools.ietf.org/html/rfc8628).
5360
AS's that assume all clients are web-based or require clients to maintain
5461
confidentiality of the client secrets may not work well.
5562

@@ -514,6 +521,125 @@ public void writeAuthState(@NonNull AuthState state) {
514521
The demo app has an [AuthStateManager](https://github.com/openid/AppAuth-Android/blob/master/app/java/net/openid/appauthdemo/AuthStateManager.java)
515522
type which demonstrates this in more detail.
516523

524+
## Implementing the device flow
525+
526+
Native apps that run on devices that lack a suitable browser integration or
527+
have limited input capabilities should use the
528+
[device flow](https://datatracker.ietf.org/doc/html/rfc8628#section-1)
529+
to authorize the limited device through another, fully capable, device.
530+
531+
This flow is effectively composed of 4 stages:
532+
533+
1. Discovering or specifying the endpoints to interact with the provider.
534+
2. Exchanging the client identifier to the authorization server to obtain a
535+
device code, an end-user code and the end-user verification URI.
536+
3. The end-user enters the code provided by the authorization server at the
537+
verification URI on a fully capable device, proceeds through the
538+
authentication flow and reviews the authorization request associated to the
539+
code.
540+
4. While the end-user completes the authorization process on the other device,
541+
polling on the authorization server most be performed with the device code
542+
and client identifier to obtain a refresh token and/or ID token.
543+
544+
### Authorization service configuration
545+
546+
The authorization service configuration construction is the same as for the
547+
regular authorization flow.
548+
549+
Refer to the authorization code flow
550+
[authorization service configuration](#authorization-service-configuration)
551+
and use the according constructor to build a configuration with a device
552+
authorization endpoint in case of manual creation, otherwise, verify that your
553+
authorization server exposes a device authorization endpoint through the OpenID
554+
Connect discovery document.
555+
556+
### Obtaining an end-user code
557+
558+
A device authorization request can be performed to obtain the device
559+
verification URI and the end-user code by constructing a
560+
`DeviceAuthorizationRequest`, using its Builder:
561+
562+
```java
563+
DeviceAuthorizationRequest deviceAuthRequest =
564+
new DeviceAuthorizationRequest.Builder(authorizationServiceConfiguration, clientId)
565+
.setScope("openid email profile")
566+
.build();
567+
```
568+
569+
The request can then be executed through the `AuthorizationService`:
570+
571+
```java
572+
authService.performDeviceAuthorizationRequest(
573+
deviceAuthRequest,
574+
new AuthorizationService.DeviceAuthorizationResponseCallback() {
575+
@Override public void onDeviceAuthorizationRequestCompleted(
576+
DeviceAuthorizationResponse resp, AuthorizationException ex) {
577+
if (resp != null) {
578+
// device authorization succeeded
579+
} else {
580+
// authorization failed, check ex for more details
581+
}
582+
}
583+
});
584+
```
585+
586+
The response can be provided to the `AuthState` instance for easy persistence
587+
and further processing:
588+
589+
```java
590+
authState.update(resp, ex);
591+
```
592+
593+
### Exchanging the end-user code
594+
595+
Given a successful device authorization response carrying an end-user code,
596+
a token request can be made to exchange the code for a refresh token:
597+
598+
```java
599+
authService.performTokenPollRequestRequest(
600+
resp.createTokenExchangeRequest(),
601+
resp.tokenPollingIntervalTime,
602+
resp.codeExpirationTime,
603+
new AuthorizationService.TokenResponseCallback() {
604+
@Override public void onTokenRequestCompleted(
605+
TokenResponse resp, AuthorizationException ex) {
606+
if (resp != null) {
607+
// exchange succeeded
608+
} else {
609+
// authorization failed, check ex for more details
610+
}
611+
}
612+
});
613+
```
614+
615+
Alternatively, the `AuthState` exposes a helper method to perform the polling
616+
after a successful device authorization request has been completed:
617+
618+
```java
619+
authState.performTokenPollRequest(authService,
620+
new AuthorizationService.TokenResponseCallback() {
621+
@Override public void onTokenRequestCompleted(
622+
TokenResponse resp, AuthorizationException ex) {
623+
if (resp != null) {
624+
// exchange succeeded
625+
} else {
626+
// authorization failed, check ex for more details
627+
}
628+
}
629+
});
630+
```
631+
632+
In both use cases, the token response can then be used to update an `AuthState`
633+
instance:
634+
635+
```java
636+
authState.update(resp, ex);
637+
```
638+
639+
### Ending current session
640+
641+
Revoking ID tokens and refresh tokens is currently not supported.
642+
517643
## Advanced configuration
518644

519645
AppAuth provides some advanced configuration options via

0 commit comments

Comments
 (0)