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 */
034public class JsonWebToken {
035
036    private static ObjectMapper mapper = new ObjectMapper();
037    private Map<String, Object> header;
038    private Map<String, Object> payload;
039    private byte[] signature;
040
041    /**
042     * Parses the given token as JWT.
043     *
044     * @param token the token
045     * @return the json web token
046     */
047    public static JsonWebToken parse(String token) {
048        try {
049            var result = new JsonWebToken();
050            var tokenizer = new StringTokenizer(token, ".");
051            result.header = convertPart(tokenizer.nextToken());
052            result.payload = convertPart(tokenizer.nextToken());
053            result.signature
054                = Base64.getUrlDecoder().decode(tokenizer.nextToken());
055            return result;
056        } catch (JsonProcessingException e) {
057            throw new UncheckedIOException(e);
058        }
059    }
060
061    private static Map<String, Object> convertPart(String part)
062            throws JsonMappingException, JsonProcessingException {
063        return mapper.readValue(new String(Base64.getUrlDecoder().decode(part)),
064            TypeFactory.defaultInstance()
065                .constructMapType(HashMap.class, String.class, Object.class));
066    }
067
068    /**
069     * Gets the header.
070     *
071     * @return the header
072     */
073    public Map<String, Object> header() {
074        return header;
075    }
076
077    /**
078     * Gets the payload.
079     *
080     * @return the payload
081     */
082    public Map<String, Object> payload() {
083        return payload;
084    }
085
086    /**
087     * Gets the signature.
088     *
089     * @return the signature
090     */
091    @SuppressWarnings("PMD.MethodReturnsInternalArray")
092    public byte[] signature() {
093        return signature;
094    }
095
096}