简体   繁体   中英

How do I create an Access Token from Service Account Credentials using REST API using JAVA?

I need to list folders using service account credentials without using the GCP Java client library. I need to call using REST API as there is restriction on making use of GCP Java client library. Is there any sample or example I can refer to make REST API calls in Java/Spring?

You can use RestTemplate and this dependency

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.14.0</version>
        </dependency>

Then, read your service account JSON file (here my key.json file) and enjoy! Let me know if some part are not clear!


        InputStream resource = new ClassPathResource("key.json").getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(resource));
        String keyFileJson = reader.lines().collect(Collectors.joining("\n"));
        Map keyFile = new ObjectMapper().readValue(keyFileJson, Map.class);


        String privKeyPEM = keyFile.get("private_key").toString().replace("-----BEGIN PRIVATE KEY-----","")
                .replace("-----END PRIVATE KEY-----","")
                .replaceAll("\n","");

        byte [] encoded = Base64.decode(privKeyPEM);

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PrivateKey privKey = kf.generatePrivate(keySpec);

        String tokenUrl = "https://oauth2.googleapis.com/token";

        long now = System.currentTimeMillis();
        Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey)privKey);
        String signedJwt = JWT.create()
                .withKeyId(keyFile.get("private_key_id").toString())
                .withIssuer(keyFile.get("client_email").toString())
                .withAudience(tokenUrl)
                .withClaim("scope","openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/compute")
                .withIssuedAt(new Date(now))
                .withExpiresAt(new Date(now + 3600 * 1000L))
                .sign(algorithm);
//        System.out.println(signedJwt);


        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("assertion", signedJwt);
        map.add("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(tokenUrl, entity, String.class);
        Map result = new ObjectMapper().readValue(responseEntity.getBody(), Map.class);
        System.out.println(result.get("access_token"));

EDIT 1

To generate and get an ID_Token, required if you want to generate a token to call Cloud Run, Cloud Functions or App Engine deployed in secured mode. You need to replace the scope claim by the target_audience URL. And at the end, print the id_token and not the access token

        String signedJwt = JWT.create()
                .withKeyId(keyFile.get("private_key_id").toString())
                .withIssuer(keyFile.get("client_email").toString())
                .withAudience(tokenUrl)
                .withClaim("target_audience", "https://target-log-fqffbf2xsq-uc.a.run.app")
                .withIssuedAt(new Date(now))
                .withExpiresAt(new Date(now + 3600 * 1000L))
                .sign(algorithm);

...
...
...
System.out.println(result.get("id_token"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM