Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion META-INF/keycloak-scripts.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
{
"authenticators": [],
"authenticators": [
{
"name": "User Enabled Authenticator",
"fileName": "user-enabled-authenticator.js",
"description": "Allow only enabled users"
},
{
"name": "CSM Authenticator",
"fileName": "csm-authenticator.js",
"description": "CSM EmployeeStatus Authenticator"
},
{
"name": "Authorization Authenticator",
"fileName": "authz-authenticator.js",
"description": "Authorization Authenticator"
}
],
"policies": [],
"mappers": [],
"saml-mappers": [
Expand Down
34 changes: 34 additions & 0 deletions authz-authenticator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

function authenticate(context) {

if (!authenticationSession.getClient()) {
context.failure(AuthenticationFlowError.CLIENT_NOT_FOUND);
return;
}
var client = authenticationSession.getClient().getClientId();
LOG.info(script.name + " evalute authorization for user=" + user.username + " client=" + client);
/*
Use employeeStatus verification for service-now which allows some disabled
states to still authenticate.
Also allow class-dev for testing purposes.
*/
if (client && (client.contains("service-now") || client.contains("class-dev"))) {
var allowed = /(REQAPPROVAL|ACTIVE|WEBONLY|RESTRICTED)/;
var employeeStatus = user.getFirstAttribute("employeeStatus");
if (employeeStatus && !allowed.test(employeeStatus)) {
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}
} else {
/*
All other clients will authorize if the user account is not disabled or locked
*/
if (user.getFirstAttribute("nsAccountLock") == "TRUE" || user.getFirstAttribute("loginDisabled") == "TRUE") {
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}
}

context.success();
}
7 changes: 4 additions & 3 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
FROM rockylinux:8
RUN dnf -y install java-17-openjdk-devel maven && yum clean all && rm -rf /var/cache/yum/*
RUN alternatives --set java $(alternatives --display java | grep 'family java-17-openjdk' | cut -d' ' -f1)
RUN alternatives --set javac $(alternatives --display javac | grep 'family java-17-openjdk' | cut -d' ' -f1)
RUN dnf -y install java-21-openjdk-devel maven && yum clean all && rm -rf /var/cache/yum/*
RUN alternatives --set java $(alternatives --display java | grep 'family java-21-openjdk' | cut -d' ' -f1)
RUN alternatives --set javac $(alternatives --display javac | grep 'family java-21-openjdk' | cut -d' ' -f1)
RUN mkdir /build
ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk
1 change: 0 additions & 1 deletion build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ From root of repo:

```
docker run --rm -it -v $(pwd):/build -w /build \
-e JAVA_HOME=/usr/lib/jvm/java-17-openjdk \
osc-keycloak-scripts-build:latest mvn clean package
```
16 changes: 16 additions & 0 deletions csm-authenticator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

function authenticate(context) {

LOG.info(script.name + " --> trace auth for: " + user.username);

const allowed = /(REQAPPROVAL|ACTIVE|WEBONLY|RESTRICTED)/;
if (user.getFirstAttribute("employeeStatus") && allowed.test(user.getFirstAttribute("employeeStatus"))) {
context.success();
} else {
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}

context.success();
}
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

<groupId>edu.osc</groupId>
<artifactId>osc-keycloak-scripts</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<packaging>jar</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17.0.0</java.version>
<java.version>21.0.0</java.version>
</properties>

<dependencies>
Expand All @@ -23,7 +23,7 @@
</dependencies>

<build>
<finalName>osc-keycloak-scripts</finalName>
<finalName>osc-keycloak-scripts-${project.version}</finalName>
<resources>
<resource>
<directory>.</directory>
Expand Down
13 changes: 13 additions & 0 deletions user-enabled-authenticator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

function authenticate(context) {

LOG.info(script.name + " --> trace auth for: " + user.username);

if (user.getFirstAttribute("nsAccountLock") == "TRUE" || user.getFirstAttribute("loginDisabled") == "TRUE") {
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}

context.success();
}