14
14
15
15
package net .openid .appauth ;
16
16
17
+ import static net .openid .appauth .AdditionalParamsProcessor .builtInParams ;
18
+
17
19
import android .net .Uri ;
18
20
import android .text .TextUtils ;
19
21
import android .util .Base64 ;
26
28
import org .json .JSONObject ;
27
29
28
30
import java .util .ArrayList ;
31
+ import java .util .Collections ;
29
32
import java .util .List ;
33
+ import java .util .Map ;
34
+ import java .util .Set ;
30
35
31
36
/**
32
37
* An OpenID Connect ID Token. Contains claims about the authentication of an End-User by an
38
43
* @see "OpenID Connect Core ID Token Validation, Section 3.1.3.7
39
44
* <http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation>"
40
45
*/
41
- class IdToken {
46
+ public class IdToken {
42
47
43
48
private static final String KEY_ISSUER = "iss" ;
44
49
private static final String KEY_SUBJECT = "sub" ;
@@ -50,41 +55,107 @@ class IdToken {
50
55
private static final Long MILLIS_PER_SECOND = 1000L ;
51
56
private static final Long TEN_MINUTES_IN_SECONDS = 600L ;
52
57
58
+ private static final Set <String > BUILT_IN_CLAIMS = builtInParams (
59
+ KEY_ISSUER ,
60
+ KEY_SUBJECT ,
61
+ KEY_AUDIENCE ,
62
+ KEY_EXPIRATION ,
63
+ KEY_ISSUED_AT ,
64
+ KEY_NONCE ,
65
+ KEY_AUTHORIZED_PARTY );
66
+
67
+ /**
68
+ * Issuer Identifier for the Issuer of the response.
69
+ */
70
+ @ NonNull
53
71
public final String issuer ;
72
+
73
+ /**
74
+ * Subject Identifier. A locally unique and never reassigned identifier within the Issuer
75
+ * for the End-User.
76
+ */
77
+ @ NonNull
54
78
public final String subject ;
79
+
80
+ /**
81
+ * Audience(s) that this ID Token is intended for.
82
+ */
83
+ @ NonNull
55
84
public final List <String > audience ;
85
+
86
+ /**
87
+ * Expiration time on or after which the ID Token MUST NOT be accepted for processing.
88
+ */
89
+ @ NonNull
56
90
public final Long expiration ;
91
+
92
+ /**
93
+ * Time at which the JWT was issued.
94
+ */
95
+ @ NonNull
57
96
public final Long issuedAt ;
97
+
98
+ /**
99
+ * String value used to associate a Client session with an ID Token,
100
+ * and to mitigate replay attacks.
101
+ */
102
+ @ Nullable
58
103
public final String nonce ;
104
+
105
+ /**
106
+ * Authorized party - the party to which the ID Token was issued.
107
+ * If present, it MUST contain the OAuth 2.0 Client ID of this party.
108
+ */
109
+ @ Nullable
59
110
public final String authorizedParty ;
60
111
112
+ /**
113
+ * Additional claims present in this ID Token.
114
+ */
115
+ @ NonNull
116
+ public final Map <String , Object > additionalClaims ;
117
+
61
118
@ VisibleForTesting
62
119
IdToken (@ NonNull String issuer ,
63
120
@ NonNull String subject ,
64
121
@ NonNull List <String > audience ,
65
122
@ NonNull Long expiration ,
66
123
@ NonNull Long issuedAt ) {
67
- this (issuer , subject , audience , expiration , issuedAt , null , null );
124
+ this (issuer , subject , audience , expiration , issuedAt , null , null , Collections . emptyMap () );
68
125
}
69
126
127
+ @ VisibleForTesting
70
128
IdToken (@ NonNull String issuer ,
71
129
@ NonNull String subject ,
72
130
@ NonNull List <String > audience ,
73
131
@ NonNull Long expiration ,
74
132
@ NonNull Long issuedAt ,
75
133
@ Nullable String nonce ,
76
134
@ Nullable String authorizedParty ) {
135
+ this (issuer , subject , audience , expiration , issuedAt ,
136
+ nonce , authorizedParty , Collections .emptyMap ());
137
+ }
138
+
139
+ IdToken (@ NonNull String issuer ,
140
+ @ NonNull String subject ,
141
+ @ NonNull List <String > audience ,
142
+ @ NonNull Long expiration ,
143
+ @ NonNull Long issuedAt ,
144
+ @ Nullable String nonce ,
145
+ @ Nullable String authorizedParty ,
146
+ @ NonNull Map <String , Object > additionalClaims ) {
77
147
this .issuer = issuer ;
78
148
this .subject = subject ;
79
149
this .audience = audience ;
80
150
this .expiration = expiration ;
81
151
this .issuedAt = issuedAt ;
82
152
this .nonce = nonce ;
83
153
this .authorizedParty = authorizedParty ;
154
+ this .additionalClaims = additionalClaims ;
84
155
}
85
156
86
157
private static JSONObject parseJwtSection (String section ) throws JSONException {
87
- byte [] decodedSection = Base64 .decode (section ,Base64 .URL_SAFE );
158
+ byte [] decodedSection = Base64 .decode (section , Base64 .URL_SAFE );
88
159
String jsonString = new String (decodedSection );
89
160
return new JSONObject (jsonString );
90
161
}
@@ -100,19 +171,24 @@ static IdToken from(String token) throws JSONException, IdTokenException {
100
171
parseJwtSection (sections [0 ]);
101
172
JSONObject claims = parseJwtSection (sections [1 ]);
102
173
103
- String issuer = JsonUtil .getString (claims , KEY_ISSUER );
104
- String subject = JsonUtil .getString (claims , KEY_SUBJECT );
174
+ final String issuer = JsonUtil .getString (claims , KEY_ISSUER );
175
+ final String subject = JsonUtil .getString (claims , KEY_SUBJECT );
105
176
List <String > audience ;
106
177
try {
107
178
audience = JsonUtil .getStringList (claims , KEY_AUDIENCE );
108
179
} catch (JSONException jsonEx ) {
109
180
audience = new ArrayList <>();
110
181
audience .add (JsonUtil .getString (claims , KEY_AUDIENCE ));
111
182
}
112
- Long expiration = claims .getLong (KEY_EXPIRATION );
113
- Long issuedAt = claims .getLong (KEY_ISSUED_AT );
114
- String nonce = JsonUtil .getStringIfDefined (claims , KEY_NONCE );
115
- String authorizedParty = JsonUtil .getStringIfDefined (claims , KEY_AUTHORIZED_PARTY );
183
+ final Long expiration = claims .getLong (KEY_EXPIRATION );
184
+ final Long issuedAt = claims .getLong (KEY_ISSUED_AT );
185
+ final String nonce = JsonUtil .getStringIfDefined (claims , KEY_NONCE );
186
+ final String authorizedParty = JsonUtil .getStringIfDefined (claims , KEY_AUTHORIZED_PARTY );
187
+
188
+ for (String key : BUILT_IN_CLAIMS ) {
189
+ claims .remove (key );
190
+ }
191
+ Map <String , Object > additionalClaims = JsonUtil .toMap (claims );
116
192
117
193
return new IdToken (
118
194
issuer ,
@@ -121,7 +197,8 @@ static IdToken from(String token) throws JSONException, IdTokenException {
121
197
expiration ,
122
198
issuedAt ,
123
199
nonce ,
124
- authorizedParty
200
+ authorizedParty ,
201
+ additionalClaims
125
202
);
126
203
}
127
204
0 commit comments