{"id":28370634,"url":"https://github.com/esotericsoftware/oauth","last_synced_at":"2025-06-26T14:31:46.337Z","repository":{"id":153853739,"uuid":"109612126","full_name":"EsotericSoftware/oauth","owner":"EsotericSoftware","description":"Making OAuth in Java dead simple","archived":false,"fork":false,"pushed_at":"2025-06-05T00:30:34.000Z","size":838,"stargazers_count":21,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-21T15:39:16.858Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EsotericSoftware.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-11-05T20:07:24.000Z","updated_at":"2025-06-06T07:11:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"47cc2ca5-4cbf-46d8-a866-b3aadcc9ce25","html_url":"https://github.com/EsotericSoftware/oauth","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/EsotericSoftware/oauth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EsotericSoftware%2Foauth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EsotericSoftware%2Foauth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EsotericSoftware%2Foauth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EsotericSoftware%2Foauth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EsotericSoftware","download_url":"https://codeload.github.com/EsotericSoftware/oauth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EsotericSoftware%2Foauth/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262084695,"owners_count":23256287,"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":[],"created_at":"2025-05-29T06:43:34.372Z","updated_at":"2025-06-26T14:31:46.276Z","avatar_url":"https://github.com/EsotericSoftware.png","language":"Java","readme":"# Simple OAuth for Java\n\nThis library is a single, ~150 LOC class which makes using OAuth 2.0 from Java very easy.\n\n## Examples\n\nFor simplicity, these examples set the client secret. Keep in mind that embedding the client secret has [security implications](#Security), though it still makes sense for some scenarios.\n\n### Slack\n\nCreate the OAuth instance:\n\n```java\nOAuth oauth = new OAuth(\"slack\", \"yourClientID\",\n\t\"yourRedirectURL\",\n\t\"https://slack.com/oauth/authorize\", // authorize URL\n\t\"https://slack.com/api/oauth.access\", // access token URL\n\t\"dnd:write\", // scopes (for \"do not disturb\")\n\t4); // concurrent HTTP requests\noauth.setClientSecret(\"yourClientSecret\"); // Note security implications below.\n```\n\nCreate/load and initialize a `Token` instance:\n\n```java\nToken token = ... // Load token from disk.\nif (oauth.authorize(token)) {\n\t// Save token to disk.\n}\n```\n\nFinally, use the access token to make requests:\n\n```java\n// Slack access tokens never expire, so just use the access token.\nHttpGet request = new HttpGet(\"https://slack.com/api/dnd.setSnooze?num_minutes=60\");\nrequest.setHeader(\"Authorization\", \"Bearer \" + token.accessToken);\nhttpRequest(request);\n```\n\n### Spotify\n\n```java\noauth = new OAuth(\"spotify\", \"yourClientID\",\n\t\"yourRedirectURL\",\n\t\"https://accounts.spotify.com/authorize\", // authorize URL\n\t\"https://accounts.spotify.com/api/token\", // access token URL\n\t\"user-modify-playback-state\", // scopes\n\t4); // concurrent HTTP requests\noauth.setClientSecret(\"yourClientSecret\"); // Note security implications below.\n\n...\n\nToken token = ... // Load token from disk.\nif (oauth.authorize(token)) {\n\t// Save token to disk.\n}\n\n...\n\n// Spotify access tokens expire, so call refreshAccessToken just before using the access token.\nif (oauth.refreshAccessToken(token)) {\n\t// Save token to disk.\n}\nHttpPut request = new HttpPut(\"https://api.spotify.com/v1/me/player/play\");\nrequest.setHeader(\"Authorization\", \"Bearer \" + accessToken);\nhttpRequest(request);\n```\n\n### Google\n\n```java\noauth = new OAuth(\"google\", \"yourClientID\",\n\t\"urn:ietf:wg:oauth:2.0:oob\", // redirect URL\n\t\"https://accounts.google.com/o/oauth2/v2/auth\", // authorize URL\n\t\"https://www.googleapis.com/oauth2/v4/token\", // access token URL\n\t\"https://www.googleapis.com/auth/assistant-sdk-prototype\", // scopes (for Google Assistant)\n\t4); // concurrent HTTP requests\noauth.setClientSecret(\"yourClientSecret\"); // Note security implications below.\n\n...\n\nToken token = ... // Load token from disk.\nif (oauth.authorize(token)) {\n\t// Save token to disk.\n}\n\n...\n\nEmbeddedAssistantGrpc.EmbeddedAssistantStub client;\nclient = EmbeddedAssistantGrpc.newStub(ManagedChannelBuilder.forAddress(\"embeddedassistant.googleapis.com\", 443).build());\n\nif (oauth.refreshAccessToken(token)) {\n\t// Save token to disk.\n}\n// Google's stuff to set the access token.\nOAuth2Credentials credentials = new OAuth2Credentials(new AccessToken(accessToken, new Date(expirationTime)));\nclient = client.withCallCredentials(MoreCallCredentials.from(credentials));\n// Google's stuff to use the Google Assistant API.\nStreamObserver\u003cConverseResponse\u003e observer = ...\nclient.converse(observer);\n```\n\n## Security\n\nThe examples above embed the client secret in the application, which only makes sense if the application is used in a secure enviroment. For example, when the client secret is owned by the user running the application and the application containing the client secret is not distributed to others. Otherwise, the client secret can be extracted and used to impersonate the application.\n\nIf a client secret has been set, the default implementation opens the specified URL in a browser and prompts the user to paste the authorization code at the command line. Next the authorization code and client secret are used to obtain an access token, which is ready for the application to use.\n\nIf a client secret has not been set, then the `obtainAccessToken` method must be overridden:\n\n```java\noauth = new OAuth(\"someService\", \"yourClientID\",\n\t\"yourRedirectURL\",\n\t\"serviceAuthorizeURL\",\n\t\"serviceAccessTokenURL\",\n\t\"serviceScopes\", \n\t4\n) {\n\tprotected void obtainAccessToken (Token token, String url) throws IOException {\n\t\t// your code here\n\t}\n}\n```\n\nThe `obtainAccessToken` method should have the user visit the specified `url` and allow access. Then the user is forwarded with a one-time use authorization code to `yourRedirectURL`, which is your web service that uses the authorization code to obtain an access token, refresh token, and expiration milliseconds. The application should retrieve those from your web service and set the corresponding 3 fields on the specified `token`. The web service should only give the access token to authenticated users.\n\nThe web service obtains the access token, refresh token, and expiration milliseconds by doing an HTTP POST to `serviceAccessTokenURL` with a POST body of:\n\n```\ncode=usersAuthorizationCode\u0026redirect_uri=yourRedirectURL\u0026client_id=yourClientID\u0026client_secret=yourClientSecret\u0026grant_type=authorization_code\n```\n\nAs you can see, obtaining the access token requires your client secret, which ensures only your app can approve access. Your web service ensures the client secret is not leaked and only gives an access token to users it has authenticated.\n\n## Utilities\n\n### JsonBeans\n\n[JsonBeans](https://github.com/EsotericSoftware/jsonbeans/) is used by the `OAuth` class and makes it easy to save/load the `Token` instance:\n\n```java\nFile file = ...\nJson json = new Json();\nToken token = file.exists() ? json.fromJson(Token.class, file) : new Token();\nif (oauth.authorize(token)) {\n\tjson.toJson(token, new FileWriter(file));\n}\n```\n\n### HttpClient\n\nMost of the examples above use [Apache HttpClient](https://hc.apache.org/httpcomponents-client-ga/), which the `OAuth` class depends on. Here is the `httpRequest` method:\n\n```java\nint connectionPoolSize = 4;\nPoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();\nconnectionManager.setMaxTotal(connectionPoolSize);\nconnectionManager.setDefaultMaxPerRoute(connectionPoolSize);\nCloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();\n\n...\n\npublic String httpRequest (HttpUriRequest request) throws IOException {\n\tHttpEntity entity = null;\n\ttry (CloseableHttpResponse response = httpClient.execute(request)) {\n\t\tString body = \"\";\n\t\tentity = response.getEntity();\n\t\tif (entity != null) {\n\t\t\tInputStream input = entity.getContent();\n\t\t\tif (input != null) {\n\t\t\t\ttry (Scanner scanner = new Scanner(input, \"UTF-8\").useDelimiter(\"\\\\A\")) {\n\t\t\t\t\tif (scanner.hasNext()) body = scanner.next().trim();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tint status = response.getStatusLine().getStatusCode();\n\t\tif (status \u003c 200 || status \u003e= 300)\n\t\t\tthrow new IOException(response.getStatusLine().toString() + (body.length() \u003e 0 ? \"\\n\" + body : \"\"));\n\t\treturn body;\n\t} finally {\n\t\tif (entity != null) EntityUtils.consumeQuietly(entity);\n\t}\n}\n```\n\nIf using HttpClient in your app like this, `httpClient` can be passed to the `OAuth` constructor to share the same instance.\n\n### Logging\n\n[MinLog](https://github.com/EsotericSoftware/minlog/) is used for logging, which is easily disabled or redirected.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesotericsoftware%2Foauth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fesotericsoftware%2Foauth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fesotericsoftware%2Foauth/lists"}