This is a minimal zero-dependency implementation of the RFC 8252 OAuth 2.0 for Native Apps, relying on Loopback Interface Redirection (i.e. no need to register a private-use URI scheme) with full support for PKCE and CSRF Protection.
- Java 11+
- Ideally some JSON or JWT parser of your choice
This library requires an instance of java.net.http.HttpClient
.
// usually the default is sufficent:
var httpClient = HttpClient.newHttpClient();
// but feel free to adjust it to your needs, e.g. by applying custom proxy settings:
var httpClient = HttpClient.newBuilder()
.proxy(ProxySelector.of(InetSocketAddress.createUnresolved("https:\\example.com",1337)))
.build();
Now to begin, start building an OAuth 2.0 Client via the fluent API:
var oauthClient = TinyOAuth2.client("oauth-client-id") // The client identifier
.withTokenEndpoint(URI.create("https://login.example.com/oauth2/token")) // The token endpoint
.withRequestTimeout(Duration.ofSeconds(10)) // optional
// ...
Next, continue with a specific grant type by invoking .authorizationCodeGrant(...)
or .clientCredentialsGrant(...)
(more may be added eventually).
Usually, you would want to use the Authorization Code Grant type to obtain access tokens.
Configure your Authorization Server to allow http://127.0.0.1/*
as a redirect target and look up the authorization endpoint:
// this library will just perform the Authorization Flow:
var httpResponse = oauthClient.authorizationCodeGrant(URI.create("https://login.example.com/oauth2/authorize"))
.authorize(httpClient, uri -> System.out.println("Please login on " + uri), "openid", "profile"); // optionally add scopes here);
If your authorization server doesn't allow wildcards, you can also configure a fixed path (and even port) via e.g. setRedirectPath("/callback")
and setRedirectPorts(8080)
before calling authorize(...)
.
Alternatively, if your client shall act on behalf of a service account, use the Client Credentials Grant type, which allows the client to authenticate directly without further user interaction:
var httpResponse = oauthClient.clientCredentialsGrant(UTF_8, "client secret")
.authorize(httpClient, "openid", "profile"); // optionally add scopes here
For maximum flexibility and minimal attack surface, this library does not include or depend on a specific parser. Instead, use a JSON or JWT parser of your choice to parse the Authorization Server's response:
if (httpResponse.statusCode() == 200) {
var jsonString = httpResponse.body()
var bearerToken = parseJson(jsonString).get("access_token");
// ...
}
- Often you just need to authorize your client and nothing more. Most OAuth2 libraries try to do a lot more
- Nano-tiny-minuscule attack surface, since this doesn't contain any JOSE/JWT signature code, nor a fully-fledged web server
- Focus is strictly on the authorization flow. Use any library for dealing with the tokens, you like.
- Modular jar, exposing only one single public API. No need to read docs, you can't do anything wrong.