Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejava
titleIOAuthDataStore & ClientData clases
linenumberstrue
collapsetrue
public interface IOAuthDataStore {
	/**
	 * Gives the datastore its configuration
	 * @param config Configuration
	 */
	public void setConfiguration(Properties config) throws ConfigurationException;
	
	/**
	 * Gives the datastore its configuration
	 * @param config Configuration
	 * @param json JSON Configuration
	 */
	public void setConfiguration(Properties config, JSONObject json) throws ConfigurationException, JSONException;
	
	/**
	 * Return a list of known client IDs
	 * @return List of known client IDs
	 */
	public Collection<String> getKnownClientIDs();
	
	/**
	 * Returns known ClientData from a clientID
	 * 
	 * @param clientID Client ID
	 * @return Client Data - includes secret, valid scopes, valid redirect URIs etc.
	 */
	public ClientData getClientData(String clientID);
	
	default void initialize(PTSServer sessionController) {
	}
}

public class ClientData {
	public enum AccessTokenType {
		JWT, UUID, RFC9068, RFC9060UP
	}
	
	/** Client ID */
	public String clientID;
	/** Client secret */
	public String clientSecret;
	/** Valid OAuth2 grant type; implicit, authorization_code */
	public Collection<String> validGrantTypes;
	/** Valid scopes, e.g. email, profile, name, photo */
	public Collection<String> allowedScopes;
	/** Allowed redirect URIs */
	public Collection<String> allowedUris;
	/** Allowed logout URIs */
	public Collection<String> allowedLogoutUris;
	/** Number of seconds the access token is valid for */
	public int accessTokenValiditySeconds;
	/** Number of seconds the refresh token is valid for */
	public int refreshTokenValiditySeconds;
	
	/** The maximum expiration time in minutes allowed */
	public int maximumIdTokenExpirationMinutes;
	/** Name of token configuration to use with this client */
	public String tokenname;
	/** Type of access token to generate */
	public AccessTokenType accessTokenType;
	
	/** A list of roles for this client - could be roles for an API partner */
	public List<String> roles;
	
	public Map<String, Object> properties = new LinkedHashMap<>();
	
	public String toJSON() {
		JSONObject jo = new JSONObject();
		try {
			jo.put("client_id", clientID);
			jo.put("client_secret", clientSecret);
			jo.put("valid_grant_types", validGrantTypes);
			jo.put("allowed_scopes", allowedScopes);
			jo.put("allowed_uris", allowedUris);
			jo.put("allowed_logout_uris", allowedLogoutUris);
			jo.put("accesstoken_valid_seconds", accessTokenValiditySeconds);
			jo.put("refreshtoken_validity_seconds", refreshTokenValiditySeconds);
			jo.put("maximum_idtoken_expiration_minutes", maximumIdTokenExpirationMinutes);
			jo.put("tokenname", tokenname);
			jo.put("accesstoken_type", accessTokenType.toString());
			
			for(String key : properties.keySet()) {
				if (!jo.has(key))
					jo.put(key,  properties.get(key));
			}
			return jo.toString();
		} catch(JSONException e) {
			return "{\"error\": \"" + JSONObject.quote(e.toString())+"\"}";
		}
	}
	
	public static ClientData fromJSON(JSONObject jo) throws JSONException {
		ClientData cd = new ClientData();
		cd.clientID = jo.optString("client_id", null);
		cd.clientSecret = jo.optString("client_secret", null);
		cd.validGrantTypes = fromJA(jo.optJSONArray("valid_grant_types"));
		cd.allowedScopes = fromJA(jo.optJSONArray("allowed_scopes"));
		cd.allowedUris = fromJA(jo.optJSONArray("allowed_uris"));
		cd.allowedLogoutUris = fromJA(jo.optJSONArray("allowed_logout_uris"));
		cd.accessTokenValiditySeconds = jo.optInt("accesstoken_valid_seconds");
		cd.refreshTokenValiditySeconds = jo.optInt("refreshTokenValiditySeconds");
		cd.maximumIdTokenExpirationMinutes = jo.optInt("maximumIdTokenExpirationMinutes");
		cd.tokenname = jo.optString("tokenname", null);
		cd.accessTokenType = AccessTokenType.valueOf(jo.optString("accesstoken_type", "UUID").toUpperCase());
		
		for(String key : JSONObject.getNames(jo)) {
			cd.properties.put(key, jo.get(key));
		}
		return cd;
	}
	
	private static Collection<String> fromJA(JSONArray ja) throws JSONException {
		if (ja == null || ja.length() == 0)
			return Collections.emptyList();
		
		List<String> result = new ArrayList<>(ja.length());
		for(int i = 0; i < ja.length(); i++) {
			result.add(ja.getString(i));
		}
		return result;
	}
}

...

Type of access token to issuer - either UUID or JWT/RFC9068/RFC9068UP - if UUID, the token itself does not contain any attributes, and the OAuth2 introspection (or userinfo) URL must be called using the access token to get any of the attributes related to it. If the type is JWT, the access token is similar to the ID token a signed JWT token containing the attributes itself.

For JWT tokens, RFC9068 / RFC9068UP are variants of JWT tokens where they set the "typ" header value to "at-jwt" or "at-JWT" respectively.

Info
titleWhy RFC9068 / RFC9068UP

RFC 9068 (seeĀ https://www.rfc-editor.org/rfc/rfc9068.html) mentions in the textual description and registration section that the type must be set to "at-jwt" but the examples within it set it to "at-JWT" with JWT in uppercase. Since some client might care about the case, you can select the type RFC9068 for the lowercase version, but also RFC9068UP for the uppercase version used in the examples.


Default: NoneUUID
JSON key is accesstoken_type

...