@@ -22,12 +22,17 @@ including using
2222for 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 )
2626extension to OAuth which was created to secure authorization codes in public
2727clients when custom URI scheme redirects are used. The library is friendly to
2828other extensions (standard or otherwise) with the ability to handle additional
2929parameters 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+
3136A talk providing an overview of using the library for enterprise single sign-on (produced by
3237Google) 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
5055In general, AppAuth can work with any Authorization Server (AS) that supports
5156native 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 ) .
5360AS's that assume all clients are web-based or require clients to maintain
5461confidentiality of the client secrets may not work well.
5562
@@ -514,6 +521,125 @@ public void writeAuthState(@NonNull AuthState state) {
514521The demo app has an [ AuthStateManager] ( https://github.com/openid/AppAuth-Android/blob/master/app/java/net/openid/appauthdemo/AuthStateManager.java )
515522type 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
519645AppAuth provides some advanced configuration options via
0 commit comments