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