001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2022 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 * 
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.webconlet.oidclogin;
020
021import com.fasterxml.jackson.core.JsonProcessingException;
022import com.fasterxml.jackson.databind.JsonMappingException;
023import com.fasterxml.jackson.databind.ObjectMapper;
024import com.fasterxml.jackson.databind.type.TypeFactory;
025import java.io.UncheckedIOException;
026import java.util.Base64;
027import java.util.HashMap;
028import java.util.Map;
029import java.util.StringTokenizer;
030
031/**
032 * The Class OidcProviderData.
033 */
034@SuppressWarnings("PMD.DataClass")
035public class JsonWebToken {
036
037    private static ObjectMapper mapper = new ObjectMapper();
038    private Map<String, Object> header;
039    private Map<String, Object> payload;
040    private byte[] signature;
041
042    /**
043     * Parses the given token as JWT.
044     *
045     * @param token the token
046     * @return the json web token
047     */
048    public static JsonWebToken parse(String token) {
049        try {
050            var result = new JsonWebToken();
051            var tokenizer = new StringTokenizer(token, ".");
052            result.header = convertPart(tokenizer.nextToken());
053            result.payload = convertPart(tokenizer.nextToken());
054            result.signature
055                = Base64.getUrlDecoder().decode(tokenizer.nextToken());
056            return result;
057        } catch (JsonProcessingException e) {
058            throw new UncheckedIOException(e);
059        }
060    }
061
062    private static Map<String, Object> convertPart(String part)
063            throws JsonMappingException, JsonProcessingException {
064        return mapper.readValue(new String(Base64.getUrlDecoder().decode(part)),
065            TypeFactory.defaultInstance()
066                .constructMapType(HashMap.class, String.class, Object.class));
067    }
068
069    /**
070     * Gets the header.
071     *
072     * @return the header
073     */
074    public Map<String, Object> header() {
075        return header;
076    }
077
078    /**
079     * Gets the payload.
080     *
081     * @return the payload
082     */
083    public Map<String, Object> payload() {
084        return payload;
085    }
086
087    /**
088     * Gets the signature.
089     *
090     * @return the signature
091     */
092    @SuppressWarnings("PMD.MethodReturnsInternalArray")
093    public byte[] signature() {
094        return signature;
095    }
096
097}