001package com.nimbusds.openid.connect.sdk.token; 002 003 004import java.util.Set; 005 006import com.nimbusds.jwt.JWT; 007 008import net.jcip.annotations.Immutable; 009 010import net.minidev.json.JSONObject; 011 012import com.nimbusds.jwt.JWTParser; 013 014import com.nimbusds.oauth2.sdk.ParseException; 015import com.nimbusds.oauth2.sdk.token.AccessToken; 016import com.nimbusds.oauth2.sdk.token.RefreshToken; 017import com.nimbusds.oauth2.sdk.token.Tokens; 018import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 019 020 021/** 022 * ID token, access token and optional refresh token. 023 */ 024@Immutable 025public final class OIDCTokens extends Tokens { 026 027 028 /** 029 * The ID Token serialised to a JWT. If not specified then the 030 * serialised variant. 031 */ 032 private final JWT idToken; 033 034 035 /** 036 * The ID Token as raw string (for more efficient serialisation). If 037 * not specified then the unserialised variant. 038 */ 039 private final String idTokenString; 040 041 042 /** 043 * Creates a new OpenID Connect tokens instance. 044 * 045 * @param idToken The ID token. Must not be {@code null}. 046 * @param accessToken The access token. Must not be {@code null}. 047 * @param refreshToken The refresh token. If none {@code null}. 048 */ 049 public OIDCTokens(final JWT idToken, final AccessToken accessToken, final RefreshToken refreshToken) { 050 051 super(accessToken, refreshToken); 052 053 if (idToken == null) { 054 throw new IllegalArgumentException("The ID token must not be null"); 055 } 056 057 this.idToken = idToken; 058 idTokenString = null; 059 } 060 061 062 /** 063 * Creates a new OpenID Connect tokens instance. 064 * 065 * @param idTokenString The ID token string. Must not be {@code null}. 066 * @param accessToken The access token. Must not be {@code null}. 067 * @param refreshToken The refresh token. If none {@code null}. 068 */ 069 public OIDCTokens(final String idTokenString, final AccessToken accessToken, final RefreshToken refreshToken) { 070 071 super(accessToken, refreshToken); 072 073 if (idTokenString == null) { 074 throw new IllegalArgumentException("The ID token string must not be null"); 075 } 076 077 this.idTokenString = idTokenString; 078 idToken = null; 079 } 080 081 082 /** 083 * Gets the ID token. 084 * 085 * @return The ID token, {@code null} if none or if parsing to a JWT 086 * failed. 087 */ 088 public JWT getIDToken() { 089 090 if (idToken != null) 091 return idToken; 092 093 if (idTokenString != null) { 094 095 try { 096 return JWTParser.parse(idTokenString); 097 098 } catch (java.text.ParseException e) { 099 100 return null; 101 } 102 } 103 104 return null; 105 } 106 107 108 /** 109 * Gets the ID token string. 110 * 111 * @return The ID token string, {@code null} if none or if 112 * serialisation to a string failed. 113 */ 114 public String getIDTokenString() { 115 116 if (idTokenString != null) 117 return idTokenString; 118 119 if (idToken != null) { 120 121 // Reproduce originally parsed string if any 122 if (idToken.getParsedString() != null) 123 return idToken.getParsedString(); 124 125 try { 126 return idToken.serialize(); 127 128 } catch(IllegalStateException e) { 129 130 return null; 131 } 132 } 133 134 return null; 135 } 136 137 138 @Override 139 public Set<String> getParameterNames() { 140 141 Set<String> paramNames = super.getParameterNames(); 142 paramNames.add("id_token"); 143 return paramNames; 144 } 145 146 147 @Override 148 public JSONObject toJSONObject() { 149 150 JSONObject o = super.toJSONObject(); 151 o.put("id_token", getIDTokenString()); 152 return o; 153 } 154 155 156 /** 157 * Parses an OpenID Connect tokens instance from the specified JSON 158 * object. 159 * 160 * @param jsonObject The JSON object to parse. Must not be {@code null}. 161 * 162 * @return The OpenID Connect tokens. 163 * 164 * @throws ParseException If the JSON object couldn't be parsed to an 165 * OpenID Connect tokens instance. 166 */ 167 public static OIDCTokens parse(final JSONObject jsonObject) 168 throws ParseException { 169 170 JWT idToken; 171 172 try { 173 idToken = JWTParser.parse(JSONObjectUtils.getString(jsonObject, "id_token")); 174 175 } catch (java.text.ParseException e) { 176 177 throw new ParseException("Couldn't parse ID token: " + e.getMessage(), e); 178 } 179 180 return new OIDCTokens(idToken, AccessToken.parse(jsonObject), RefreshToken.parse(jsonObject)); 181 } 182}