001package com.nimbusds.jwt;
002
003
004import java.text.ParseException;
005
006import net.minidev.json.JSONObject;
007
008import com.nimbusds.jose.Algorithm;
009import com.nimbusds.jose.Header;
010import com.nimbusds.jose.JWEAlgorithm;
011import com.nimbusds.jose.JWSAlgorithm;
012import com.nimbusds.jose.util.Base64URL;
013import com.nimbusds.jose.util.JSONObjectUtils;
014
015
016/**
017 * Parser for plain, signed and encrypted JSON Web Tokens (JWTs).
018 *
019 * @author Vladimir Dzhuvinov
020 * @author Junya Hayashi
021 * @version $version$ (2014-11-14)
022 */
023public final class JWTParser {
024
025
026        /**
027         * Parses a plain, signed or encrypted JSON Web Token (JWT) from the
028         * specified string in compact format.
029         *
030         * @param s The string to parse. Must not be {@code null}.
031         *
032         * @return The corresponding {@link PlainJWT}, {@link SignedJWT} or
033         *         {@link EncryptedJWT} instance.
034         *
035         * @throws ParseException If the string couldn't be parsed to a valid 
036         *                        plain, signed or encrypted JWT.
037         */
038        public static JWT parse(final String s)
039                throws ParseException {
040
041                final int firstDotPos = s.indexOf(".");
042                
043                if (firstDotPos == -1)
044                        throw new ParseException("Invalid JWT serialization: Missing dot delimiter(s)", 0);
045                        
046                Base64URL header = new Base64URL(s.substring(0, firstDotPos));
047                
048                JSONObject jsonObject;
049
050                try {
051                        jsonObject = JSONObjectUtils.parseJSONObject(header.decodeToString());
052
053                } catch (ParseException e) {
054
055                        throw new ParseException("Invalid plain/JWS/JWE header: " + e.getMessage(), 0);
056                }
057
058                Algorithm alg = Header.parseAlgorithm(jsonObject);
059
060                if (alg.equals(Algorithm.NONE)) {
061                        return PlainJWT.parse(s);
062                } else if (alg instanceof JWSAlgorithm) {
063                        return SignedJWT.parse(s);
064                } else if (alg instanceof JWEAlgorithm) {
065                        return EncryptedJWT.parse(s);
066                } else {
067                        throw new AssertionError("Unexpected algorithm type: " + alg);
068                }
069        }
070
071
072        /**
073         * Parses a plain, signed or encrypted JSON Web Token (JWT) from the
074         * specified string in compact format.
075         *
076         * @param s       The string to parse. Must not be {@code null}.
077         * @param handler Handler for the parsed JWT. Must not be {@code null}.
078         *
079         * @return The object returned by the handler, {@code null} if none is
080         *         returned.
081         *
082         * @throws ParseException If the string couldn't be parsed to a valid
083         *                        plain, signed or encrypted JWT.
084         */
085        public static <T> T parse(final String s, final JWTHandler<T> handler)
086                throws ParseException {
087
088                JWT jwt = parse(s);
089
090                if (jwt instanceof PlainJWT) {
091                        return handler.onPlainJWT((PlainJWT)jwt);
092                } else if (jwt instanceof SignedJWT) {
093                        return handler.onSignedJWT((SignedJWT)jwt);
094                } else {
095                        return handler.onEncryptedJWT((EncryptedJWT)jwt);
096                }
097        }
098
099
100        /**
101         * Prevents instantiation.
102         */
103        private JWTParser() {
104
105        }
106}