001package com.nimbusds.oauth2.sdk.auth;
002
003
004import java.util.Date;
005import java.util.List;
006
007import net.minidev.json.JSONObject;
008
009import com.nimbusds.jwt.JWTClaimsSet;
010
011import com.nimbusds.oauth2.sdk.ParseException;
012import com.nimbusds.oauth2.sdk.assertions.jwt.JWTAssertionDetails;
013import com.nimbusds.oauth2.sdk.id.Audience;
014import com.nimbusds.oauth2.sdk.id.ClientID;
015import com.nimbusds.oauth2.sdk.id.Issuer;
016import com.nimbusds.oauth2.sdk.id.JWTID;
017import com.nimbusds.oauth2.sdk.id.Subject;
018
019
020/**
021 * JWT client authentication claims set, serialisable to a JSON object and JWT 
022 * claims set.
023 *
024 * <p>Used for {@link ClientSecretJWT client secret JWT} and
025 * {@link PrivateKeyJWT private key JWT} authentication at the Token endpoint.
026 *
027 * <p>Example client authentication claims set:
028 *
029 * <pre>
030 * {
031 *   "iss" : "http://client.example.com",
032 *   "sub" : "http://client.example.com",
033 *   "aud" : [ "http://idp.example.com/token" ],
034 *   "jti" : "d396036d-c4d9-40d8-8e98-f7e8327002d9",
035 *   "exp" : 1311281970,
036 *   "iat" : 1311280970
037 * }
038 * </pre>
039 *
040 * <p>Related specifications:
041 *
042 * <ul>
043 *     <li>OAuth 2.0 (RFC 6749), section-3.2.1.
044 *     <li>JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and
045 *         Authorization Grants (RFC 7523).
046 * </ul>
047 */
048public class JWTAuthenticationClaimsSet extends JWTAssertionDetails {
049
050
051        /**
052         * Creates a new JWT client authentication claims set. The expiration
053         * time (exp) is set to five minutes from the current system time.
054         * Generates a default identifier (jti) for the JWT. The issued-at
055         * (iat) and not-before (nbf) claims are not set.
056         *
057         * @param clientID The client identifier. Used to specify the issuer
058         *                 and the subject. Must not be {@code null}.
059         * @param aud      The audience identifier, typically the URI of the
060         *                 authorisation server's Token endpoint. Must not be
061         *                 {@code null}.
062         */
063        public JWTAuthenticationClaimsSet(final ClientID clientID,
064                                          final Audience aud) {
065
066                this(clientID, aud.toSingleAudienceList(), new Date(new Date().getTime() + 5*60* 1000L), null, null, new JWTID());
067        }
068
069        
070        /**
071         * Creates a new JWT client authentication claims set.
072         *
073         * @param clientID The client identifier. Used to specify the issuer 
074         *                 and the subject. Must not be {@code null}.
075         * @param aud      The audience, typically including the URI of the
076         *                 authorisation server's Token endpoint. Must not be 
077         *                 {@code null}.
078         * @param exp      The expiration time. Must not be {@code null}.
079         * @param nbf      The time before which the token must not be 
080         *                 accepted for processing, {@code null} if not
081         *                 specified.
082         * @param iat      The time at which the token was issued, 
083         *                 {@code null} if not specified.
084         * @param jti      Unique identifier for the JWT, {@code null} if
085         *                 not specified.
086         */
087        public JWTAuthenticationClaimsSet(final ClientID clientID,
088                                          final List<Audience> aud,
089                                          final Date exp,
090                                          final Date nbf,
091                                          final Date iat,
092                                          final JWTID jti) {
093
094                super(new Issuer(clientID.getValue()), new Subject(clientID.getValue()), aud, exp, nbf, iat, jti, null);
095        }
096
097
098        /**
099         * Gets the client identifier. Corresponds to the {@code iss} and
100         * {@code sub} claims.
101         *
102         * @return The client identifier.
103         */
104        public ClientID getClientID() {
105
106                return new ClientID(getIssuer());
107        }
108        
109        /**
110         * Parses a JWT client authentication claims set from the specified 
111         * JSON object.
112         *
113         * @param jsonObject The JSON object. Must not be {@code null}.
114         *
115         * @return The client authentication claims set.
116         *
117         * @throws ParseException If the JSON object couldn't be parsed to a 
118         *                        client authentication claims set.
119         */
120        public static JWTAuthenticationClaimsSet parse(final JSONObject jsonObject)
121                throws ParseException {
122                
123                JWTAssertionDetails assertion = JWTAssertionDetails.parse(jsonObject);
124
125                return new JWTAuthenticationClaimsSet(
126                        new ClientID(assertion.getIssuer()), // iss=sub
127                        assertion.getAudience(),
128                        assertion.getExpirationTime(),
129                        assertion.getNotBeforeTime(),
130                        assertion.getIssueTime(),
131                        assertion.getJWTID());
132        }
133
134
135        /**
136         * Parses a JWT client authentication claims set from the specified JWT 
137         * claims set.
138         *
139         * @param jwtClaimsSet The JWT claims set. Must not be {@code null}.
140         *
141         * @return The client authentication claims set.
142         *
143         * @throws ParseException If the JWT claims set couldn't be parsed to a 
144         *                        client authentication claims set.
145         */
146        public static JWTAuthenticationClaimsSet parse(final JWTClaimsSet jwtClaimsSet)
147                throws ParseException {
148                
149                return parse(jwtClaimsSet.toJSONObject());
150        }
151}