Skip to content

caseykulm/oauthheader

Repository files navigation

OAuth Header

Maven Central

An OkHttp helper for generating the four bits needed for 3 legged OAuth.

  1. Request Token
  2. Authorize
  3. Access Token
  4. Resource Request Signing oauthheader

Download

With Gradle:

dependencies {
  implementation 'com.caseykulm.oauthheader:oauthheader:0.5.0'
}

Steps from scratch

Step 0: Define your OAuth constants

Define the key and secret generated for your app by the Service. Also define the callback URL you would like the Service to send the Request Token to.

val oauthConsumer = OauthConsumer(
  "YOUR_CONSUMER_KEY", 
  "YOUR_CONSUMER_SECRET", 
  "YOUR_CONSUMER_CALLBACK"
)

Define the 3 OAuth endpoints from the Service, or use one of the predefined OauthService objects from the oauthheader-services artifact.

val oauthService = OauthService(
  "SERVICE_REQUEST_TOKEN_URL", 
  "SERVICE_AUTHORIZE_URL", 
  "SERVICE_ACCESS_TOKEN_URL"
)

Create an Oauth1Api instance with the Oauth1Client class.

val oauthClient = Oauth1Client(
  oauthConsumer, 
  oauthService, 
  okhttpClient
)

Step 1: Get a Request Token

Kick off the first request to get the request token which we will use later.

val requestTokenResponse: RequestTokenResponse = oauthClient.getRequestToken()

Step 2: Get a formatted Authorization URL

This will form the url you should send your users to. If you set the callback url, the data for the next step will be sent there.

val authorizationUrl: String = oauthClient.getAuthorizationUrl(requestTokenResponse)

Step 3: Intercept the Authorization Response

You should intercept the query string from the Oauth page calling your callback and it will look something like this

val rawQueryStr = "oauth_token=123abc&oauth_verifier"

Then you should use this helper to parse the response to check if it is valid, and to pass as input to the next step.

val authorizationResponse: AuthorizationResponse = oauthClient.parseVerificationResponse(rawQueryStr)

Step 4: Get a Access Token

Now you can get an access token.

val accessTokenResponse: AccessTokenResponse = oauthClient.getAccessToken(
  requestTokenResponse, authorizationResponse
)

Step 5: Getting a Signed Resource Request Header

Your request for a resource on Service, that will require OAuth, might look something like this.

val body = FormBody.Builder()
    .add("status", "Hello Ladies + Gentlemen, a signed OAuth request!")
    .build()
val resourceRequest = Request.Builder()
    .url("https://api.twitter.com/1/statuses/update.json?include_entities=true")
    .post(body)
    .build()

OkHttp Interceptor to add header to each request

You can now use the provided helper interceptor.

val oauthInterceptor = Oauth1Interceptor(oauth1Client, accessTokenResponse)

And add it to your OkHttpClient instance.

val oauthSessionClient = unauthedClient.newBuilder()
  .addInterceptor(oauthInterceptor)
  .build()

Manually add header to each request

Or you can manually get a signed header from the oauthClient, providing the stuff we've acquired so far.

val signedHeaderValue: String = oauthClient.getSignedResourceAuthHeader(
  resourceRequest, authorizationResponse, accessTokenResponse
)

Add it to your resource request, also using the provided constant for the Header Key.

val signedResourceRequest = resourceRequest.newBuilder()
  .addHeader(Oauth1Client.AUTH_HEADER_KEY, signedHeaderValue)
  .build()

And now you're good to send off an authenticated requests 🎉

Steps after Authenticating Once

You need to persist both the AccessTokenResponse and the AuthorizationResponse in order to avoid needing to do Steps 1-4 in the future.

Assuming you have those, you should just be able to perform Step 5 for every request to the service moving forward.

Reauthorizing

Although the signedResourceRequest will usually work, you should expect that it can return 401 at any point, do to multiple reasons such as the user revoking your client apps access, your consumer values being revoked/expired, etc.

If that happens then you should proceed from Step 1.

About

OkHttp OAuth 1.0 3-legged Helper

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages