Skip to content

Instantly share code, notes, and snippets.

@binshi
Created January 27, 2017 11:21
Show Gist options
  • Save binshi/bce40ca171ac4ac00b01d9a27bb44926 to your computer and use it in GitHub Desktop.
Save binshi/bce40ca171ac4ac00b01d9a27bb44926 to your computer and use it in GitHub Desktop.
Simple class to get access token based on service key
import java.io.{IOException, StringReader, Reader, ByteArrayInputStream}
import java.nio.charset.Charset
import java.security.{NoSuchAlgorithmException, KeyFactory, PrivateKey}
import java.security.spec.{InvalidKeySpecException, PKCS8EncodedKeySpec}
import java.util.Collections
import com.google.api.client.json.webtoken.{JsonWebToken, JsonWebSignature}
import com.google.api.client.json.{JsonFactory, GenericJson, JsonObjectParser}
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.client.util.{SecurityUtils, PemReader, Joiner}
import com.google.api.services.androidpublisher.AndroidPublisherScopes
class ServiceAccountApiAccess {
val jsonKey = """{
"type": "service_account",
"project_id": "project-XXXXXXX",
"private_key_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"private_key": "-----BEGIN PRIVATE KEY-----\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n-----END PRIVATE KEY-----\n",
"client_email": "XXXXXXX@api-project-yyyyyyyyyyyyyy.iam.gserviceaccount.com",
"client_id": "zzzzzzzzzzzzzzzzzzzzzzzzzzzz",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/XXXXXXX@api-project-yyyyyyyyyyyyyy.iam.gserviceaccount.com"
} """
val credentialStream = new ByteArrayInputStream(jsonKey.getBytes())
val parser: JsonObjectParser = new JsonObjectParser(JacksonFactory.getDefaultInstance())
val fileContents: GenericJson = parser.parseAndClose(credentialStream, Charset.forName("UTF-8"), classOf[GenericJson])
val clientId: String = fileContents.get("client_id").asInstanceOf[String]
val clientEmail: String = fileContents.get("client_email").asInstanceOf[String]
val privateKeyPem: String = fileContents.get("private_key").asInstanceOf[String]
val privateKeyId: String = fileContents.get("private_key_id").asInstanceOf[String]
val privateKey: PrivateKey = privateKeyFromPkcs8(privateKeyPem)
val header: JsonWebSignature.Header = new JsonWebSignature.Header
header.setAlgorithm("RS256")
header.setType("JWT")
header.setKeyId(privateKeyId)
val payload: JsonWebToken.Payload = new JsonWebToken.Payload
val currentTime: Long = System.currentTimeMillis()
payload.setIssuer(clientEmail)
payload.setAudience("https://www.googleapis.com/oauth2/v4/token")
payload.setIssuedAtTimeSeconds(currentTime / 1000)
payload.setExpirationTimeSeconds(currentTime / 1000 + 3600)
payload.setSubject(null)
payload.put("scope", Joiner.on(' ').join(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER)))
val jsonFactory: JsonFactory = JacksonFactory.getDefaultInstance
try{
var assertion: String = JsonWebSignature.signUsingRsaSha256(privateKey, jsonFactory, header, payload)
println(assertion)
}catch {
case ex:Exception => ex.printStackTrace()
}
def privateKeyFromPkcs8(privateKeyPem: String):PrivateKey = {
val reader: Reader = new StringReader(privateKeyPem)
val section: PemReader.Section = PemReader.readFirstSectionAndClose(reader, "PRIVATE KEY")
if (section == null) {
throw new IOException("Invalid PKCS8 data.")
}
val bytes: Array[Byte] = section.getBase64DecodedBytes
val keySpec: PKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(bytes)
var unexpectedException: Exception = null
try {
val keyFactory: KeyFactory = SecurityUtils.getRsaKeyFactory
val privateKey: PrivateKey = keyFactory.generatePrivate(keySpec)
privateKey
}
catch {
case exception: NoSuchAlgorithmException => {
unexpectedException = exception
}
case exception: InvalidKeySpecException => {
unexpectedException = exception
}
}
val keyFactory: KeyFactory = SecurityUtils.getRsaKeyFactory
val privateKey: PrivateKey = keyFactory.generatePrivate(keySpec)
privateKey
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment