2014-07-21 3 views
3

내 Java 응용 프로그램에서 기본 OpenID 연결 흐름을 구현했으며 제대로 작동하는 것 같습니다.OpenID Connect - Java에서 ID 토큰을 확인하는 방법?

기존 Java 라이브러리를 사용하여 OpenID 연결 구현에 대한 as detailed here on a Salesforce page ID 토큰을 확인하고 싶습니다.

이 우물을 구현하는 기존 라이브러리가 있습니까? 내가 응답을 구문 분석있어, 난 그냥 ID 토큰이 유효한지 확인하는 몇 가지 간단한 방법을 찾아야합니다.

+1

본 적이 있습니까? [ID 토큰 유효화] (https://developers.google.com/accounts/docs/OAuth2Login?hl=ja#validatinganidtoken)? 심지어 예제와 함께 사용할 샘플 Java 코드도 있습니다. – Rainbolt

+0

흠! 좋아 보인다 - 내일 다시 시도해보고 어떻게 될지보고 .... Google+에 너무 바빠서는 안된다. 감사! –

+0

salesforce의 경우 확인 작업을 관리하는 방법을 자세히 설명하는 문서는 다음에서 볼 수 있습니다. https://help.salesforce.com/HTViewHelpDoc?id=remoteaccess_using_id_token.htm&language=en_US –

답변

7

다음 예는 타사 라이브러리가없는 Salesforce의 OAuth2 호출에서 id_token의 유효성을 검사합니다. 이를 테스트하려면 아래에 유효한 id_token을 제공해야합니다.

package jwt_validate_signature_sf_no_third_party; 

import java.math.BigInteger; 
import java.nio.charset.StandardCharsets; 
import java.security.GeneralSecurityException; 
import java.security.KeyFactory; 
import java.security.PublicKey; 
import java.security.Signature; 
import java.security.spec.RSAPublicKeySpec; 
import org.apache.commons.codec.binary.Base64; 

public class Main 
{ 
    // Sample id_token that needs validation. This is probably the only field you need to change to test your id_token. 
    // If it doesn't work, try making sure the MODULUS and EXPONENT constants are what you're using, as detailed below. 
    public static final String id_token = "YOUR_ID_TOKEN_HERE"; 
    public static final String[] id_token_parts = id_token.split("\\."); 

    // Constants that come from the keys your token was signed with. 
    // Correct values can be found from using the "kid" value and looking up the "n (MODULUS)" and "e (EXPONENT)" fields 
    // at the following url: https://login.salesforce.com/id/keys 
    //  MAJOR NOTE: This url will work for 90% of your use cases, but for the other 10% 
    //  you'll need to make sure you get the "kid" value from the instance url that 
    //  the api responses from Salesforce suggest for your token, as the kid values *will* be different. 
    //  e.g. Some users would need to get their kid values from https://na44.salesforce.com/id/keys for example. 
    // The following 2 values are hard coded to work with the "kid=196" key values. 
    public static final String MODULUS = "5SGw1jcqyFYEZaf39RoxAhlq-hfRSOsneVtsT2k09yEQhwB2myvf3ckVAwFyBF6y0Hr1psvu1FlPzKQ9YfcQkfge4e7eeQ7uaez9mMQ8RpyAFZprq1iFCix4XQw-jKW47LAevr9w1ttZY932gFrGJ4gkf_uqutUny82vupVUETpQ6HDmIL958SxYb_-d436zi5LMlHnTxcR5TWIQGGxip-CrD7vOA3hrssYLhNGQdwVYtwI768EvwE8h4VJDgIrovoHPH1ofDQk8-oG20eEmZeWugI1K3z33fZJS-E_2p_OiDVr0EmgFMTvPTnQ75h_9vyF1qhzikJpN9P8KcEm8oGu7KJGIn8ggUY0ftqKG2KcWTaKiirFFYQ981PhLHryH18eOIxMpoh9pRXf2y7DfNTyid99ig0GUH-lzAlbKY0EV2sIuvEsIoo6G8YT2uI72xzl7sCcp41FS7oFwbUyHp_uHGiTZgN7g-18nm2TFmQ_wGB1xCwJMFzjIXq1PwEjmg3W5NBuMLSbG-aDwjeNrcD_4vfB6yg548GztQO2MpV_BuxtrZDJQm-xhJXdm4FfrJzWdwX_JN9qfsP0YU1_mxtSU_m6EKgmwFdE3Yh1WM0-kRRSk3gmNvXpiKeVduzm8I5_Jl7kwLgBw24QUVaLZn8jC2xWRk_jcBNFFLQgOf9U"; 
    public static final String EXPONENT = "AQAB"; 

    public static final String ID_TOKEN_HEADER = base64UrlDecode(id_token_parts[0]); 
    public static final String ID_TOKEN_PAYLOAD = base64UrlDecode(id_token_parts[1]); 
    public static final byte[] ID_TOKEN_SIGNATURE = base64UrlDecodeToBytes(id_token_parts[2]); 

    public static String base64UrlDecode(String input) 
    { 
     byte[] decodedBytes = base64UrlDecodeToBytes(input); 
     String result = new String(decodedBytes, StandardCharsets.UTF_8); 
     return result; 
    } 

    public static byte[] base64UrlDecodeToBytes(String input) 
    { 
     Base64 decoder = new Base64(-1, null, true); 
     byte[] decodedBytes = decoder.decode(input); 

     return decodedBytes; 
    } 

    public static void main(String args[]) 
    { 
     dumpJwtInfo(); 
     validateToken(); 
    } 

    public static void dump(String data) 
    { 
     System.out.println(data); 
    } 

    public static void dumpJwtInfo() 
    { 
     dump(ID_TOKEN_HEADER); 
     dump(ID_TOKEN_PAYLOAD); 
    } 

    public static void validateToken() 
    { 
     PublicKey publicKey = getPublicKey(MODULUS, EXPONENT); 
     byte[] data = (id_token_parts[0] + "." + id_token_parts[1]).getBytes(StandardCharsets.UTF_8); 

     try 
     { 
      boolean isSignatureValid = verifyUsingPublicKey(data, ID_TOKEN_SIGNATURE, publicKey); 
      System.out.println("isSignatureValid: " + isSignatureValid); 
     } 
     catch (GeneralSecurityException e) 
     { 
      e.printStackTrace(); 
     } 

    } 

    public static PublicKey getPublicKey(String MODULUS, String EXPONENT) 
    { 
     byte[] nb = base64UrlDecodeToBytes(MODULUS); 
     byte[] eb = base64UrlDecodeToBytes(EXPONENT); 
     BigInteger n = new BigInteger(1, nb); 
     BigInteger e = new BigInteger(1, eb); 

     RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(n, e); 
     try 
     { 
      PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(rsaPublicKeySpec); 

      return publicKey; 
     } 
     catch (Exception ex) 
     { 
      throw new RuntimeException("Cant create public key", ex); 
     } 
    } 

    private static boolean verifyUsingPublicKey(byte[] data, byte[] signature, PublicKey pubKey) throws GeneralSecurityException 
    { 
     Signature sig = Signature.getInstance("SHA256withRSA"); 
     sig.initVerify(pubKey); 
     sig.update(data); 

     return sig.verify(signature); 
    } 
} 

참고가 잘 작동대로, 타사 라이브러리, I'd totally suggest using this를 사용하여 반대하지 않는 경우. 비즈니스 목적으로는 사용할 수 없지만이 프로세스가 어떻게 작동하는지 이해하는 데 도움이 됨으로써 찾을 수있어서 기뻤습니다 id_token의 유효성을 확인했습니다. 훨씬 더 강력한 방법으로 확신합니다.

또한이 요청이 동일한 클라이언트에 의해 서명되었으므로 페이로드의 aud 매개 변수가 Salesforce에서 제공 한 자신의 클라이언트 키와 일치해야합니다.

+1

내 하루를 보냈습니다! 내가 할 수 있다면, 나는 1000 upvotes 넣어 것입니다! –

2

Spring Security OAuth의 일부로 Spring 팀은 Spring Security JWT이라는 라이브러리를 개발하여 토큰의 디코딩 및 검증을 포함하여 JWT를 조작 할 수있게했습니다.

예를 들어 다음과 같은 헬퍼 클래스를 참조하십시오 :

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-jwt/src/main/java/org/springframework/security/jwt/JwtHelper.java

라이브러리는 받는다는의 repo에서 버전 1.0.0-RELEASE 및 사용 가능한입니다.

관련 문제