package de.jpaw.bonaparte.api.auth;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.joda.time.Instant;
import de.jpaw.bonaparte.core.DataAndMeta;
import de.jpaw.bonaparte.core.JsonComposer;
import de.jpaw.bonaparte.core.ListMetaComposer;
import de.jpaw.bonaparte.core.MapParser;
import de.jpaw.bonaparte.core.MimeTypes;
import de.jpaw.bonaparte.pojos.api.auth.Jwt;
import de.jpaw.bonaparte.pojos.api.auth.JwtAlg;
import de.jpaw.bonaparte.pojos.api.auth.JwtInfo;
import de.jpaw.bonaparte.pojos.api.auth.JwtPayload;
import de.jpaw.bonaparte.pojos.meta.FieldDefinition;
import de.jpaw.json.JsonException;
import de.jpaw.json.JsonParser;
import de.jpaw.util.ApplicationException;
/** Conversions between JSON strings and Bonaparte classes for parts of the JWT. */
public class JwtConverter {
private static final String PAYLOAD_PQON = JwtPayload.BClass.INSTANCE.getPqon();
/** returns the current time, rounded down to the previous full second. */
public static Instant lastFullSecond() {
long now = System.currentTimeMillis();
return new Instant(now - now % 1000L);
}
public static Map<String,Object> asMap(String json) throws JsonException {
return new JsonParser(json, true).parseObject();
}
public static JwtAlg parseAlg(String json) throws ApplicationException {
final JwtAlg alg = (JwtAlg) MapParser.asBonaPortable(new JsonParser(json, true).parseObject(), Jwt.meta$$alg);
alg.freeze();
return alg;
}
public static JwtPayload parsePayload(Map<String,Object> map) throws ApplicationException {
final JwtPayload payload = (JwtPayload) MapParser.asBonaPortable(map, Jwt.meta$$payload);
payload.freeze();
return payload;
}
public static JwtPayload parsePayload(String json) throws ApplicationException {
final Map<String,Object> map = new JsonParser(json, true).parseObject();
// if no object type has been specified, provide the default type to avoid a warning, unless fqon or pqon is specified
Object pqon1 = map.get(MimeTypes.JSON_FIELD_PQON);
Object pqon2 = map.get(MimeTypes.JSON_FIELD_FQON);
if (!((pqon1 != null && pqon1 instanceof String) || (pqon2 != null && pqon2 instanceof String)))
map.put(MimeTypes.JSON_FIELD_PQON, PAYLOAD_PQON);
return parsePayload(map);
}
public static String toJson(JwtAlg alg) {
return JsonComposer.toJsonString(alg);
}
public static String toJson(JwtPayload payload) {
return JsonComposer.toJsonString(payload);
}
public static JwtInfo parseJwtInfo(String json) throws ApplicationException {
return parseJwtInfo(parsePayload(json)); // use the intermediate object to avoid the hassle of handwritten type checks
}
public static JwtInfo parseJwtInfo(JwtPayload payload) throws ApplicationException {
final JwtInfo info = new JwtInfo();
info.setIssuer (payload.getIss());
info.setUserId (payload.getSub());
info.setAudience (payload.getAud());
info.setExpiresAt (payload.getExp());
info.setNotBefore (payload.getNbf());
info.setIssuedAt (payload.getIat());
info.setJsonTokenIdentifier (payload.getJti());
info.setName (payload.getName());
info.setLocale (payload.getLocale());
info.setZoneinfo (payload.getZoneinfo());
info.setTenantId (payload.getI());
info.setTenantRef (payload.getT());
info.setSessionRef (payload.getS());
info.setUserRef (payload.getU());
info.setRoleRef (payload.getR());
info.setSessionId (payload.getO());
info.setQuota (payload.getQ());
info.setLogLevel (payload.getL());
info.setLogLevelErrors (payload.getE());
info.setResource (payload.getP());
info.setResourceIsWildcard (payload.getW());
info.setPermissionsMin (payload.getPl());
info.setPermissionsMax (payload.getPu());
info.setZ (payload.getZ());
info.freeze();
return info;
}
// converter from JwtInfo into a JWT Map uses a composer
private static class MapWithTagKeysComposer extends ListMetaComposer {
private final Map<String,Object> target;
private final Map<String, String> properties;
private MapWithTagKeysComposer(Map<String,Object> target, Map<String, String> properties) {
super(new ArrayList<DataAndMeta>(0), false, false, false, true);
this.target = target;
this.properties = properties;
}
@Override
protected void add(FieldDefinition di, Object o) {
if (o != null) {
String key = properties.get(di.getName() + ".tag");
if (key == null) {
// throw new RuntimeException("No JWT tag defined for JwtInfo field " + di.getName());
} else {
target.put(key, o);
}
}
}
}
/** Returns the JwtInfo as a Payload map. */
public static Map<String,Object> asMap(JwtInfo info) {
final Map<String, Object> jsonMap = new HashMap<String, Object>(16);
new MapWithTagKeysComposer(jsonMap, JwtInfo.class$MetaData().getProperties()).writeObject(info);
return jsonMap;
}
}