{"id":18486723,"url":"https://github.com/openid/AppAuth-Android","last_synced_at":"2025-04-08T19:33:40.618Z","repository":{"id":37992849,"uuid":"52095564","full_name":"openid/AppAuth-Android","owner":"openid","description":"Android client SDK for communicating with OAuth 2.0 and OpenID Connect providers.","archived":false,"fork":false,"pushed_at":"2024-08-16T16:26:22.000Z","size":1531,"stargazers_count":2850,"open_issues_count":227,"forks_count":886,"subscribers_count":243,"default_branch":"master","last_synced_at":"2024-10-29T11:44:17.465Z","etag":null,"topics":["android-sdk","oauth2","openid-connect"],"latest_commit_sha":null,"homepage":"https://openid.github.io/AppAuth-Android","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-19T15:09:43.000Z","updated_at":"2024-10-29T02:40:08.000Z","dependencies_parsed_at":"2023-01-31T12:16:21.684Z","dependency_job_id":"ee449127-b06c-417c-8a6f-37b717a9f4a2","html_url":"https://github.com/openid/AppAuth-Android","commit_stats":{"total_commits":278,"total_committers":48,"mean_commits":5.791666666666667,"dds":0.7122302158273381,"last_synced_commit":"c6137b7db306d9c097c0d5763f3fb944cd0122d2"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openid%2FAppAuth-Android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openid%2FAppAuth-Android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openid%2FAppAuth-Android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openid%2FAppAuth-Android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openid","download_url":"https://codeload.github.com/openid/AppAuth-Android/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247912795,"owners_count":21017046,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android-sdk","oauth2","openid-connect"],"created_at":"2024-11-06T12:49:46.586Z","updated_at":"2025-04-08T19:33:39.901Z","avatar_url":"https://github.com/openid.png","language":"Java","funding_links":[],"categories":["安全","Java","Client Library"],"sub_categories":["Mobile"],"readme":"![AppAuth for Android](https://rawgit.com/openid/AppAuth-Android/master/appauth_lockup.svg)\n\n[![Download](https://img.shields.io/maven-central/v/net.openid/appauth)](https://search.maven.org/search?q=g:net.openid%20appauth)\n[![Javadocs](http://javadoc.io/badge/net.openid/appauth.svg)](http://javadoc.io/doc/net.openid/appauth)\n[![Build Status](https://github.com/openid/AppAuth-Android/actions/workflows/build.yml/badge.svg)](https://github.com/openid/AppAuth-Android/actions/workflows/build.yml)\n[![codecov.io](https://codecov.io/github/openid/AppAuth-Android/coverage.svg?branch=master)](https://codecov.io/github/openid/AppAuth-Android?branch=master)\n\nAppAuth for Android is a client SDK for communicating with\n[OAuth 2.0](https://tools.ietf.org/html/rfc6749) and\n[OpenID Connect](http://openid.net/specs/openid-connect-core-1_0.html) providers.\nIt strives to\ndirectly map the requests and responses of those specifications, while following\nthe idiomatic style of the implementation language. In addition to mapping the\nraw protocol flows, convenience methods are available to assist with common\ntasks like performing an action with fresh tokens.\n\nThe library follows the best practices set out in\n[RFC 8252 - OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252),\nincluding using\n[Custom Tabs](https://developer.chrome.com/multidevice/android/customtabs)\nfor authorization requests. For this reason,\n`WebView` is explicitly *not* supported due to usability and security reasons.\n\nThe library also supports the [PKCE](https://tools.ietf.org/html/rfc7636)\nextension to OAuth which was created to secure authorization codes in public\nclients when custom URI scheme redirects are used. The library is friendly to\nother extensions (standard or otherwise) with the ability to handle additional\nparameters in all protocol requests and responses.\n\nA talk providing an overview of using the library for enterprise single sign-on (produced by\nGoogle) can be found here:\n[Enterprise SSO with Chrome Custom Tabs](https://www.youtube.com/watch?v=DdQTXrk6YTk).\n\n## Download\n\nAppAuth for Android is available on [MavenCentral](https://search.maven.org/search?q=g:net.openid%20appauth)\n\n```groovy\nimplementation 'net.openid:appauth:\u003cversion\u003e'\n```\n\n## Requirements\n\nAppAuth supports Android API 16 (Jellybean) and above. Browsers which provide a custom tabs\nimplementation are preferred by the library, but not required.\nBoth Custom URI Schemes (all supported versions of Android) and App Links (Android M / API 23+) can\nbe used with the library.\n\nIn general, AppAuth can work with any Authorization Server (AS) that supports\nnative apps as documented in [RFC 8252](https://tools.ietf.org/html/rfc8252),\neither through custom URI scheme redirects, or App Links.\nAS's that assume all clients are web-based or require clients to maintain\nconfidentiality of the client secrets may not work well.\n\n## Demo app\n\nA demo app is contained within this repository. For instructions on how to\nbuild and configure this app, see the\n[demo app readme](https://github.com/openid/AppAuth-Android/blob/master/app/README.md).\n\n## Conceptual overview\n\nAppAuth encapsulates the authorization state of the user in the\n[net.openid.appauth.AuthState](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthState.java)\nclass, and communicates with an authorization server through the use of the\n[net.openid.appauth.AuthorizationService](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java)\nclass. AuthState is designed to be easily persistable as a JSON string, using\nthe storage mechanism of your choice (e.g.\n[SharedPreferences](https://developer.android.com/training/basics/data-storage/shared-preferences.html),\n[sqlite](https://developer.android.com/training/basics/data-storage/databases.html),\nor even just\n[in a file](https://developer.android.com/training/basics/data-storage/files.html)).\n\nAppAuth provides data classes which are intended to model the OAuth2\nspecification as closely as possible; this provides the greatest flexibility\nin interacting with a wide variety of OAuth2 and OpenID Connect implementations.\n\nAuthorizing the user occurs via the user's web browser, and the request\nis described using instances of\n[AuthorizationRequest](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationRequest.java).\nThe request is dispatched using\n[performAuthorizationRequest()](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java#L159) on an AuthorizationService instance, and the response (an\n[AuthorizationResponse](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationResponse.java) instance) will be dispatched to the activity of your choice,\nexpressed via an Intent.\n\nToken requests, such as obtaining a new access token using a refresh token,\nfollow a similar pattern:\n[TokenRequest](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/TokenRequest.java) instances are dispatched using\n[performTokenRequest()](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java#L252) on an AuthorizationService instance, and a\n[TokenResponse](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/TokenResponse.java)\ninstance is returned via a callback.\n\nResponses can be provided to the\n[update()](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthState.java#L367)\nmethods on AuthState in order to track and persist changes to the authorization\nstate. Once in an authorized state, the\n[performActionWithFreshTokens()](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthState.java#L449)\nmethod on AuthState can be used to automatically refresh access tokens\nas necessary before performing actions that require valid tokens.\n\n## Implementing the authorization code flow\n\nIt is recommended that native apps use the\n[authorization code](https://tools.ietf.org/html/rfc6749#section-1.3.1)\nflow with a public client to gain authorization to access user data. This has\nthe primary advantage for native clients that the authorization flow, which\nmust occur in a browser, only needs to be performed once.\n\nThis flow is effectively composed of four stages:\n\n1. Discovering or specifying the endpoints to interact with the provider.\n2. Authorizing the user, via a browser, in order to obtain an authorization\n   code.\n3. Exchanging the authorization code with the authorization server, to obtain\n   a refresh token and/or ID token.\n4. Using access tokens derived from the refresh token to interact with a\n   resource server for further access to user data.\n\nAt each step of the process, an AuthState instance can (optionally) be updated\nwith the result to help with tracking the state of the flow.\n\n### Authorization service configuration\n\nFirst, AppAuth must be instructed how to interact with the authorization\nservice. This can be done either by directly creating an\n[AuthorizationServiceConfiguration](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationServiceConfiguration.java#L102)\ninstance, or by retrieving an OpenID Connect discovery document.\n\nDirectly specifying an AuthorizationServiceConfiguration involves\nproviding the URIs of the authorization endpoint and token endpoint,\nand optionally a dynamic client registration endpoint (see \"Dynamic client\nregistration\" for more info):\n\n```java\nAuthorizationServiceConfiguration serviceConfig =\n    new AuthorizationServiceConfiguration(\n        Uri.parse(\"https://idp.example.com/auth\"), // authorization endpoint\n        Uri.parse(\"https://idp.example.com/token\")); // token endpoint\n```\n\nWhere available, using an OpenID Connect discovery document is preferable:\n\n```java\nAuthorizationServiceConfiguration.fetchFromIssuer(\n    Uri.parse(\"https://idp.example.com\"),\n    new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() {\n      public void onFetchConfigurationCompleted(\n          @Nullable AuthorizationServiceConfiguration serviceConfiguration,\n          @Nullable AuthorizationException ex) {\n        if (ex != null) {\n          Log.e(TAG, \"failed to fetch configuration\");\n          return;\n        }\n\n        // use serviceConfiguration as needed\n    }\n});\n```\n\nThis will attempt to download a discovery document from the standard location\nunder this base URI,\n`https://idp.example.com/.well-known/openid-configuration`. If the discovery\ndocument for your IDP is in some other non-standard location, you can instead\nprovide the full URI as follows:\n\n```java\nAuthorizationServiceConfiguration.fetchFromUrl(\n    Uri.parse(\"https://idp.example.com/exampletenant/openid-config\"),\n    new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() {\n        ...\n    }\n});\n```\n\nIf desired, this configuration can be used to seed an AuthState instance,\nto persist the configuration easily:\n\n```java\nAuthState authState = new AuthState(serviceConfig);\n```\n\n### Obtaining an authorization code\n\nAn authorization code can now be acquired by constructing an\nAuthorizationRequest, using its Builder. In AppAuth, the builders for each\ndata class accept the mandatory parameters via the builder constructor:\n\n```java\nAuthorizationRequest.Builder authRequestBuilder =\n    new AuthorizationRequest.Builder(\n        serviceConfig, // the authorization service configuration\n        MY_CLIENT_ID, // the client ID, typically pre-registered and static\n        ResponseTypeValues.CODE, // the response_type value: we want a code\n        MY_REDIRECT_URI); // the redirect URI to which the auth response is sent\n```\n\nOther optional parameters, such as the OAuth2\n[scope string](https://tools.ietf.org/html/rfc6749#section-3.3)\nor\nOpenID Connect\n[login hint](http://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3.1.2.1)\nare specified through set methods on the builder:\n\n```java\nAuthorizationRequest authRequest = authRequestBuilder\n    .setScope(\"openid email profile https://idp.example.com/custom-scope\")\n    .setLoginHint(\"jdoe@user.example.com\")\n    .build();\n```\n\nThis request can then be dispatched using one of two approaches.\n\na `startActivityForResult` call using an Intent returned from the\n`AuthorizationService`, or by calling `performAuthorizationRequest` and\nproviding pending intent for completion and cancelation handling activities.\n\nThe `startActivityForResult` approach is simpler to use but may require\nmore processing of the result:\n\n```java\nprivate void doAuthorization() {\n  AuthorizationService authService = new AuthorizationService(this);\n  Intent authIntent = authService.getAuthorizationRequestIntent(authRequest);\n  startActivityForResult(authIntent, RC_AUTH);\n}\n\n@Override\nprotected void onActivityResult(int requestCode, int resultCode, Intent data) {\n  if (requestCode == RC_AUTH) {\n    AuthorizationResponse resp = AuthorizationResponse.fromIntent(data);\n    AuthorizationException ex = AuthorizationException.fromIntent(data);\n    // ... process the response or exception ...\n  } else {\n    // ...\n  }\n}\n```\n\nIf instead you wish to directly transition to another activity on completion\nor cancelation, you can use `performAuthorizationRequest`:\n\n```java\nAuthorizationService authService = new AuthorizationService(this);\n\nauthService.performAuthorizationRequest(\n    authRequest,\n    PendingIntent.getActivity(this, 0, new Intent(this, MyAuthCompleteActivity.class), 0),\n    PendingIntent.getActivity(this, 0, new Intent(this, MyAuthCanceledActivity.class), 0));\n```\n\nThe intents may be customized to carry any additional data or flags required\nfor the correct handling of the authorization response.\n\n#### Capturing the authorization redirect\n\nOnce the authorization flow is completed in the browser, the authorization\nservice will redirect to a URI specified as part of the authorization request,\nproviding the response via query parameters. In order for your app to\ncapture this response, it must register with the Android OS as a handler for\nthis redirect URI.\n\nWe recommend using a custom scheme based redirect URI (i.e. those of form\n`my.scheme:/path`), as this is the most widely supported across all versions of\nAndroid. To avoid conflicts with other apps, it is recommended to configure a \ndistinct scheme using \"reverse domain name notation\". This can either match\nyour service web domain (in reverse) e.g. `com.example.service` or your package\nname `com.example.app` or be something completely new as long as it's distinct\nenough. Using the package name of your app is quite common but it's not always\npossible if it contains illegal characters for URI schemes (like underscores)\nor if you already have another handler for that scheme - so just use something\nelse.\n\nWhen a custom scheme is used, AppAuth can be easily configured to capture\nall redirects using this custom scheme through a manifest placeholder:\n\n```groovy\nandroid.defaultConfig.manifestPlaceholders = [\n  'appAuthRedirectScheme': 'com.example.app'\n]\n```\n\nAlternatively, the redirect URI can be directly configured by adding an\nintent-filter for AppAuth's RedirectUriReceiverActivity to your\nAndroidManifest.xml:\n\n```xml\n\u003cactivity\n        android:name=\"net.openid.appauth.RedirectUriReceiverActivity\"\n        tools:node=\"replace\"\u003e\n    \u003cintent-filter\u003e\n        \u003caction android:name=\"android.intent.action.VIEW\"/\u003e\n        \u003ccategory android:name=\"android.intent.category.DEFAULT\"/\u003e\n        \u003ccategory android:name=\"android.intent.category.BROWSABLE\"/\u003e\n        \u003cdata android:scheme=\"com.example.app\"/\u003e\n    \u003c/intent-filter\u003e\n\u003c/activity\u003e\n```\n\nIf an HTTPS redirect URI is required instead of a custom scheme, the same\napproach (modifying your AndroidManifest.xml) is used:\n\n```xml\n\u003cactivity\n        android:name=\"net.openid.appauth.RedirectUriReceiverActivity\"\n        tools:node=\"replace\"\u003e\n    \u003cintent-filter\u003e\n        \u003caction android:name=\"android.intent.action.VIEW\"/\u003e\n        \u003ccategory android:name=\"android.intent.category.DEFAULT\"/\u003e\n        \u003ccategory android:name=\"android.intent.category.BROWSABLE\"/\u003e\n        \u003cdata android:scheme=\"https\"\n              android:host=\"app.example.com\"\n              android:path=\"/oauth2redirect\"/\u003e\n    \u003c/intent-filter\u003e\n\u003c/activity\u003e\n```\n\nHTTPS redirects can be secured by configuring the redirect URI as an\n[app link](https://developer.android.com/training/app-links/index.html) in\nAndroid M and above. We recommend that a fallback page be configured at\nthe same address to forward authorization responses to your app via a custom\nscheme, for older Android devices.\n\n#### Handling the authorization response\n\nUpon completion of the authorization flow, the completion Intent provided to\nperformAuthorizationRequest will be triggered. The authorization response\nis provided to this activity via Intent extra data, which can be extracted\nusing the `fromIntent()` methods on AuthorizationResponse and\nAuthorizationException respectively:\n\n```java\npublic void onCreate(Bundle b) {\n  AuthorizationResponse resp = AuthorizationResponse.fromIntent(getIntent());\n  AuthorizationException ex = AuthorizationException.fromIntent(getIntent());\n  if (resp != null) {\n    // authorization completed\n  } else {\n    // authorization failed, check ex for more details\n  }\n  // ...\n}\n```\n\nThe response can be provided to the AuthState instance for easy persistence\nand further processing:\n\n```\nauthState.update(resp, ex);\n```\n\nIf the full redirect URI is required in order to extract additional information\nthat AppAuth does not provide, this is also provided to your activity:\n\n```java\npublic void onCreate(Bundle b) {\n  // ...\n  Uri redirectUri = getIntent().getData();\n  // ...\n}\n```\n\n### Exchanging the authorization code\n\nGiven a successful authorization response carrying an authorization code,\na token request can be made to exchange the code for a refresh token:\n\n```java\nauthService.performTokenRequest(\n    resp.createTokenExchangeRequest(),\n    new AuthorizationService.TokenResponseCallback() {\n      @Override public void onTokenRequestCompleted(\n            TokenResponse resp, AuthorizationException ex) {\n          if (resp != null) {\n            // exchange succeeded\n          } else {\n            // authorization failed, check ex for more details\n          }\n        }\n    });\n```\n\nThe token response can also be used to update an AuthState instance:\n\n```java\nauthState.update(resp, ex);\n```\n\n### Using access tokens\n\nFinally, the retrieved access token can be used to interact with a resource\nserver. This can be done directly, by extracting the access token from a\ntoken response. However, in most cases, it is simpler to use the\n`performActionWithFreshTokens` utility method provided by AuthState:\n\n```java\nauthState.performActionWithFreshTokens(service, new AuthStateAction() {\n  @Override public void execute(\n      String accessToken,\n      String idToken,\n      AuthorizationException ex) {\n    if (ex != null) {\n      // negotiation for fresh tokens failed, check ex for more details\n      return;\n    }\n\n    // use the access token to do something ...\n  }\n});\n```\n\nThis also updates the AuthState object with current access, id, and refresh tokens.\nIf you are storing your AuthState in persistent storage, you should write the updated\ncopy in the callback to this method.\n\n### Ending current session\n\nGiven you have a logged in session and you want to end it. In that case you need to get:\n- `AuthorizationServiceConfiguration`\n- valid Open Id Token that you should get after authentication\n- End of session URI that should be provided within you OpenId service config\n\nFirst you have to build EndSessionRequest\n\n```java\nEndSessionRequest endSessionRequest =\n    new EndSessionRequest.Builder(authorizationServiceConfiguration)\n        .setIdTokenHint(idToken)\n        .setPostLogoutRedirectUri(endSessionRedirectUri)\n        .build();\n```\nThis request can then be dispatched using one of two approaches.\n\na `startActivityForResult` call using an Intent returned from the `AuthorizationService`,\nor by calling `performEndSessionRequest` and providing pending intent for completion\nand cancelation handling activities.\n\nThe startActivityForResult approach is simpler to use but may require more processing of the result:\n\n```java\nprivate void endSession() {\n  AuthorizationService authService = new AuthorizationService(this);\n  Intent endSessionItent = authService.getEndSessionRequestIntent(endSessionRequest);\n  startActivityForResult(endSessionItent, RC_END_SESSION);\n}\n\n@Override\nprotected void onActivityResult(int requestCode, int resultCode, Intent data) {\n  if (requestCode == RC_END_SESSION) {\n    EndSessionResponse resp = EndSessionResponse.fromIntent(data);\n    AuthorizationException ex = AuthorizationException.fromIntent(data);\n    // ... process the response or exception ...\n  } else {\n    // ...\n  }\n}\n```\nIf instead you wish to directly transition to another activity on completion or cancelation,\nyou can use `performEndSessionRequest`:\n\n```java\nAuthorizationService authService = new AuthorizationService(this);\n\nauthService.performEndSessionRequest(\n    endSessionRequest,\n    PendingIntent.getActivity(this, 0, new Intent(this, MyAuthCompleteActivity.class), 0),\n    PendingIntent.getActivity(this, 0, new Intent(this, MyAuthCanceledActivity.class), 0));\n```\n\nEnd session flow will also work involving browser mechanism that is described in authorization\nmechanism session.\nHandling response mechanism with transition to another activity should be as follows:\n\n ```java\npublic void onCreate(Bundle b) {\n  EndSessionResponse resp = EndSessionResponse.fromIntent(getIntent());\n  AuthorizationException ex = AuthorizationException.fromIntent(getIntent());\n  if (resp != null) {\n    // authorization completed\n  } else {\n    // authorization failed, check ex for more details\n  }\n  // ...\n}\n```\n\n### AuthState persistence\n\nInstances of `AuthState` keep track of the authorization and token\nrequests and responses. This is the only object that you need to persist to\nretain the authorization state of the session. Typically, one would do this by\nstoring the authorization state in SharedPreferences or some other persistent\nstore private to the app:\n\n```java\n@NonNull public AuthState readAuthState() {\n  SharedPreferences authPrefs = getSharedPreferences(\"auth\", MODE_PRIVATE);\n  String stateJson = authPrefs.getString(\"stateJson\", null);\n  if (stateJson != null) {\n    return AuthState.jsonDeserialize(stateJson);\n  } else {\n    return new AuthState();\n  }\n}\n\npublic void writeAuthState(@NonNull AuthState state) {\n  SharedPreferences authPrefs = getSharedPreferences(\"auth\", MODE_PRIVATE);\n  authPrefs.edit()\n      .putString(\"stateJson\", state.jsonSerializeString())\n      .apply();\n}\n```\n\nThe demo app has an [AuthStateManager](https://github.com/openid/AppAuth-Android/blob/master/app/java/net/openid/appauthdemo/AuthStateManager.java)\ntype which demonstrates this in more detail.\n\n## Advanced configuration\n\nAppAuth provides some advanced configuration options via\n[AppAuthConfiguration](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AppAuthConfiguration.java)\ninstances, which can be provided to\n[AuthorizationService](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java)\nduring construction.\n\n### Controlling which browser is used for authorization\n\nSome applications require explicit control over which browsers can be used\nfor authorization - for example, to require that Chrome be used for\nsecond factor authentication to work, or require that some custom browser\nis used for authentication in an enterprise environment.\n\nControl over which browsers can be used can be achieved by defining a\n[BrowserMatcher](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/BrowserMatcher.java), and supplying this to the builder of AppAuthConfiguration.\nA BrowserMatcher is suppled with a\n[BrowserDescriptor](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/BrowserDescriptor.java)\ninstance, and must decide whether this browser is permitted for the\nauthorization flow.\n\nBy default, [AnyBrowserMatcher](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/AnyBrowserMatcher.java)\nis used.\n\nFor your convenience, utility classes to help define a browser matcher are\nprovided, such as:\n\n- [Browsers](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/Browsers.java):\n  contains a set of constants for the official package names and signatures\n  of Chrome, Firefox and Samsung SBrowser.\n- [VersionedBrowserMatcher](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/VersionedBrowserMatcher.java):\n  will match a browser if it has a matching package name and signature, and\n  a version number within a defined\n  [VersionRange](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/VersionRange.java). This class also provides some static instances for matching\n  Chrome, Firefox and Samsung SBrowser.\n- [BrowserAllowList](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/BrowserAllowList.java):\n  takes a list of BrowserMatcher instances, and will match a browser if any\n  of these child BrowserMatcher instances signals a match.\n- [BrowserDenyList](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/browser/BrowserDenyList.java):\n  the inverse of BrowserAllowList - takes a list of browser matcher instances,\n  and will match a browser if it _does not_ match any of these child\n  BrowserMatcher instances.\n\nFor instance, in order to restrict the authorization flow to using Chrome\nor SBrowser as a custom tab:\n\n```java\nAppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder()\n    .setBrowserMatcher(new BrowserAllowList(\n        VersionedBrowserMatcher.CHROME_CUSTOM_TAB,\n        VersionedBrowserMatcher.SAMSUNG_CUSTOM_TAB))\n    .build();\nAuthorizationService authService =\n        new AuthorizationService(context, appAuthConfig);\n```\n\nOr, to prevent the use of a buggy version of the custom tabs in\nSamsung SBrowser:\n\n```java\nAppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder()\n    .setBrowserMatcher(new BrowserDenyList(\n        new VersionedBrowserMatcher(\n            Browsers.SBrowser.PACKAGE_NAME,\n            Browsers.SBrowser.SIGNATURE_SET,\n            true, // when this browser is used via a custom tab\n            VersionRange.atMost(\"5.3\")\n        )))\n    .build();\nAuthorizationService authService =\n        new AuthorizationService(context, appAuthConfig);\n```\n\n### Customizing the connection builder for HTTP requests\n\nIt can be desirable to customize how HTTP connections are made when performing\ntoken requests, for instance to use\n[certificate pinning](https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning)\nor to add additional trusted certificate authorities for an enterprise\nenvironment. This can be achieved in AppAuth by providing a custom\n[ConnectionBuilder](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/connectivity/ConnectionBuilder.java)\ninstance.\n\nFor example, to custom the SSL socket factory used, one could do the following:\n\n```java\nAppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder()\n    .setConnectionBuilder(new ConnectionBuilder() {\n      public HttpURLConnection openConnect(Uri uri) throws IOException {\n        URL url = new URL(uri.toString());\n        HttpURLConnection connection =\n            (HttpURLConnection) url.openConnection();\n        if (connection instanceof HttpsUrlConnection) {\n          HttpsURLConnection connection = (HttpsURLConnection) connection;\n          connection.setSSLSocketFactory(MySocketFactory.getInstance());\n        }\n      }\n    })\n    .build();\n```\n\n### Issues with [ID Token](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/IdToken.java#L118) validation\n\nID Token validation was introduced in `0.8.0` but not all authorization servers or configurations support it correctly.\n\n- For testing environments [setSkipIssuerHttpsCheck](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AppAuthConfiguration.java#L129) can be used to bypass the fact the issuer needs to be HTTPS.\n\n```java\nAppAuthConfiguration appAuthConfig = new AppAuthConfiguration.Builder()\n    .setSkipIssuerHttpsCheck(true)\n    .build()\n```\n\n- For services that don't support nonce[s] resulting in **IdTokenException** `Nonce mismatch` just set nonce to `null` on the `AuthorizationRequest`. Please consider **raising an issue** with your Identity Provider and removing this once it is fixed.\n\n```java\nAuthorizationRequest authRequest = authRequestBuilder\n    .setNonce(null)\n    .build();\n```\n\n## Dynamic client registration\n\nAppAuth supports the\n[OAuth2 dynamic client registration protocol](https://tools.ietf.org/html/rfc7591).\nIn order to dynamically register a client, create a\n[RegistrationRequest](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/RegistrationRequest.java) and dispatch it using\n[performRegistrationRequest](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationService.java#L278)\non your AuthorizationService instance.\n\nThe registration endpoint can either\nbe defined directly as part of your\n[AuthorizationServiceConfiguration](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/AuthorizationServiceConfiguration.java),\nor discovered from an OpenID Connect discovery document.\n\n```java\nRegistrationRequest registrationRequest = new RegistrationRequest.Builder(\n    serviceConfig,\n    Arrays.asList(redirectUri))\n    .build();\n```\n\nRequests are dispatched with the help of `AuthorizationService`. As this\nrequest is asynchronous the response is passed to a callback:\n\n```java\nservice.performRegistrationRequest(\n    registrationRequest,\n    new AuthorizationService.RegistrationResponseCallback() {\n        @Override public void onRegistrationRequestCompleted(\n            @Nullable RegistrationResponse resp,\n            @Nullable AuthorizationException ex) {\n            if (resp != null) {\n                // registration succeeded, store the registration response\n                AuthState state = new AuthState(resp);\n                //proceed to authorization...\n            } else {\n              // registration failed, check ex for more details\n            }\n         }\n    });\n```\n\n## Utilizing client secrets (DANGEROUS)\n\nWe _strongly recommend_ you avoid using static client secrets in your\nnative applications whenever possible. Client secrets derived via a dynamic\nclient registration are safe to use, but static client secrets can be easily\nextracted from your apps and allow others to impersonate your app and steal\nuser data. If client secrets must be used by the OAuth2 provider you are\nintegrating with, we strongly recommend performing the code exchange step\non your backend, where the client secret can be kept hidden.\n\nHaving said this, in some cases using client secrets is unavoidable. In these\ncases, a [ClientAuthentication](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/ClientAuthentication.java)\ninstance can be provided to AppAuth when performing a token request. This\nallows additional parameters (both HTTP headers and request body parameters) to\nbe added to token requests. Two standard implementations of\nClientAuthentication are provided:\n\n- [ClientSecretBasic](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/ClientSecretBasic.java):\n  includes a client ID and client secret as an HTTP Basic Authorization header.\n- [ClientSecretPost](https://github.com/openid/AppAuth-Android/blob/master/library/java/net/openid/appauth/ClientSecretPost.java):\n  includes a client ID and client secret as additional request parameters.\n\nSo, in order to send a token request using HTTP basic authorization, one would\nwrite:\n\n```java\nClientAuthentication clientAuth = new ClientSecretBasic(MY_CLIENT_SECRET);\nTokenRequest req = ...;\nauthService.performTokenRequest(req, clientAuth, callback);\n```\n\nThis can also be done when using `performActionWithFreshTokens` on AuthState:\n\n```java\nClientAuthentication clientAuth = new ClientSecretPost(MY_CLIENT_SECRET);\nauthState.performActionWithFreshTokens(\n    authService,\n    clientAuth,\n    action);\n```\n\n## Modifying or contributing to AppAuth\n\nThis project requires the Android SDK for API level 25 (Nougat) to build,\nthough the produced binaries only require API level 16 (Jellybean) to be\nused. We recommend that you fork and/or clone this repository to make\nmodifications; downloading the source has been known to cause some developers\nproblems.\n\nFor contributors, see the additional instructions in\n[CONTRIBUTING.md](https://github.com/openid/AppAuth-Android/blob/master/CONTRIBUTING.md).\n\n### Building from the Command line\n\nAppAuth for Android uses Gradle as its build system. In order to build\nthe library and app binaries, run `./gradlew assemble`.\nThe library AAR files are output to `library/build/outputs/aar`, while the\ndemo app is output to `app/build/outputs/apk`.\nIn order to run the tests and code analysis, run `./gradlew check`.\n\n### Building from Android Studio\n\nIn AndroidStudio, File -\u003e New -\u003e Import project. Select the root folder\n(the one with the `build.gradle` file).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenid%2FAppAuth-Android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenid%2FAppAuth-Android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenid%2FAppAuth-Android/lists"}