...
See Setting up API Gateway for information on how to configure this using the Gateway configuration within the Console.
Session Resolver
Protecting access to these APIs is important - here is a copy from the default distribution of the session resolver setup for the internal gateway serving the Internal APIs
Code Block | ||
---|---|---|
| ||
"session": {
"cookie.not.for.uri": "*.crl",
"resolvers": ["io.ceptor.session.SessionResolverScript"],
"cookie.no.cachecontrol.header.for": "*.crl|*.pdf",
"http.cookiename": "sessionid",
"https.cookiename": "sslsessionid",
"cookie.path": "/",
"sessionfixation.cookiename": "sslsessionid_sf",
"cookie.use.httponly": true,
"sessionfixation.addcookie": true,
"sessionfixation.defense": true,
"cookie.obfuscate": true,
"cookie.use.domain": true,
"cookie.samesite": "none",
"resolve.script": "%{script:groovy}import dk.itp.security.passticket.PTException;\nimport io.undertow.util.Methods;\nimport io.undertow.util.Headers;\nimport io.undertow.util.HttpString;\n\nHttpString ACCESS_CONTROL_REQUEST_METHOD = HttpString.tryFromString(\"Access-Control-Request-Method\");\n\n// For useradmin API, just used the session ID in the query parameter, if present\nif (context.macro('%{REQUEST_PATH}').startsWith(\"/useradmin/\")) {\n String sid = context.macro('%{query:session}');\n if (sid?.trim()) {\n try {\n context.sessionId = new dk.itp.security.utils.UniqueId(sid);\n } catch(Exception e) {\n context.httpExchange.getResponseHeaders().add(io.undertow.util.HttpString.tryFromString(\"Access-Control-Allow-Origin\"), \"*\");\n context.gateway.sendAndLogError(context, 401, \"Invalid session\", e)\n }\n return;\n }\n}\n\nString authHeader = context.macro('%{requestheader:Authorization}');\n\nif (authHeader && authHeader.toLowerCase().startsWith(\"basic \")) {\n try {\n String sessionid = context.agent.getSessionFromTicket(54, authHeader.substring(6), context.config.gateway.segmentId, context.config.gateway.clusterId, context.gateway.getClientSourceIP(context), true);\n if (sessionid) {\n context.sessionId = new dk.itp.security.utils.UniqueId(sessionid);\n }\n } catch(PTException e) {\n context.httpExchange.getResponseHeaders().add(io.undertow.util.HttpString.tryFromString(\"Access-Control-Allow-Origin\"), \"*\");\n context.gateway.sendAndLogError(context, 401, \"Invalid credentials\", e)\n }\n} else if (context.httpExchange.getRequestMethod() == Methods.OPTIONS && context.httpExchange.getRequestHeaders().contains(Headers.ORIGIN) && context.httpExchange.getRequestHeaders().contains(ACCESS_CONTROL_REQUEST_METHOD)) {\n context.trace.trace(\"Allowing OPTIONS preflight request through without session\");\n} else {\n context.httpExchange.getResponseHeaders().add(io.undertow.util.HttpString.tryFromString(\"Access-Control-Allow-Origin\"), \"*\");\n context.httpExchange.getResponseHeaders().add(io.undertow.util.Headers.WWW_AUTHENTICATE, \"basic\");\n context.gateway.sendAndLogError(context, 401, \"Authentication Required\", \"Basic auth required\")\n}"
},
|
Here is the session resolver script as it looks in Groovy:
Code Block |
---|
import dk.itp.security.passticket.PTException;
import io.undertow.util.Methods;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;
HttpString ACCESS_CONTROL_REQUEST_METHOD = HttpString.tryFromString("Access-Control-Request-Method");
// For useradmin API, just used the session ID in the query parameter, if present
if (context.macro('%{REQUEST_PATH}').startsWith("/useradmin/")) {
String sid = context.macro('%{query:session}');
if (sid?.trim()) {
try {
context.sessionId = new dk.itp.security.utils.UniqueId(sid);
} catch(Exception e) {
context.httpExchange.getResponseHeaders().add(io.undertow.util.HttpString.tryFromString("Access-Control-Allow-Origin"), "*");
context.gateway.sendAndLogError(context, 401, "Invalid session", e)
}
return;
}
}
String authHeader = context.macro('%{requestheader:Authorization}');
if (authHeader && authHeader.toLowerCase().startsWith("basic ")) {
try {
String sessionid = context.agent.getSessionFromTicket(54, authHeader.substring(6), context.config.gateway.segmentId, context.config.gateway.clusterId, context.gateway.getClientSourceIP(context), true);
if (sessionid) {
context.sessionId = new dk.itp.security.utils.UniqueId(sessionid);
}
} catch(PTException e) {
context.httpExchange.getResponseHeaders().add(io.undertow.util.HttpString.tryFromString("Access-Control-Allow-Origin"), "*");
context.gateway.sendAndLogError(context, 401, "Invalid credentials", e)
}
} else if (context.httpExchange.getRequestMethod() == Methods.OPTIONS && context.httpExchange.getRequestHeaders().contains(Headers.ORIGIN) && context.httpExchange.getRequestHeaders().contains(ACCESS_CONTROL_REQUEST_METHOD)) {
context.trace.trace("Allowing OPTIONS preflight request through without session");
} else {
context.httpExchange.getResponseHeaders().add(io.undertow.util.HttpString.tryFromString("Access-Control-Allow-Origin"), "*");
context.httpExchange.getResponseHeaders().add(io.undertow.util.Headers.WWW_AUTHENTICATE, "basic");
context.gateway.sendAndLogError(context, 401, "Authentication Required", "Basic auth required")
} |
Tip |
---|
The script uses basic authentication and expects same users as the ones who can access the console - for this to work, the authentication plugin; dk.itp.security.passticket.server.ConfigServerAuthenticationPlugin must be installed in the Session Controller. |
Datastores
By default, APIs, Partners, Partner Applications and Developers (see Glossary for info) are stored in a Derby database, running on the local machine.
...