Skip to content

Commit

Permalink
feat: add Gluu Casa support
Browse files Browse the repository at this point in the history
feat: add Gluu Casa support
  • Loading branch information
iromli committed Jan 12, 2022
1 parent a90b3d5 commit 089a872
Show file tree
Hide file tree
Showing 24 changed files with 354 additions and 1,448 deletions.
11 changes: 8 additions & 3 deletions docker-jans-auth-server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,22 @@ RUN mkdir -p /usr/share/java

ARG TWILIO_VERSION=7.17.0
RUN wget -q https://repo1.maven.org/maven2/com/twilio/sdk/twilio/${TWILIO_VERSION}/twilio-${TWILIO_VERSION}.jar -O /usr/share/java/twilio.jar

ARG JSMPP_VERSION=2.3.7
RUN wget -q https://repo1.maven.org/maven2/org/jsmpp/jsmpp/${JSMPP_VERSION}/jsmpp-${JSMPP_VERSION}.jar -O /usr/share/java/jsmpp.jar

# This will later be refactored and moved to be pulled from persitence or a central bucket
ARG CASA_VERSION=5.0.0-SNAPSHOT
ARG CASA_BUILD_DATE="2022-01-05 12:52"
RUN wget -q https://jenkins.gluu.org/maven/org/gluu/casa-config/${CASA_VERSION}/casa-config-${CASA_VERSION}.jar -O /usr/share/java/casa-config.jar

# ======
# Python
# ======

COPY requirements.txt /app/requirements.txt
RUN pip3 install -U pip \
&& pip3 install --no-cache-dir --default-timeout=300 -r /app/requirements.txt \
&& rm -rf /src/jans-pycloudlib/.git
RUN pip3 install -U pip wheel \
&& pip3 install --no-cache-dir --default-timeout=300 -r /app/requirements.txt

# =======
# Cleanup
Expand Down
43 changes: 18 additions & 25 deletions docker-jans-auth-server/libs/casa-external_fido2.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
# Based on oxAuth Fido2ExternalAuthenticator.py

from javax.ws.rs.core import Response
from org.jboss.resteasy.client import ClientResponseFailure
from org.jboss.resteasy.client.exception import ResteasyClientException
from javax.ws.rs.core import Response
from org.gluu.model.custom.script.type.auth import PersonAuthenticationType
from org.gluu.fido2.client import Fido2ClientFactory
from org.gluu.oxauth.security import Identity
from org.gluu.oxauth.service import AuthenticationService, UserService, SessionIdService
from org.gluu.oxauth.util import ServerUtil
from org.gluu.service.cdi.util import CdiUtil
from org.gluu.util import StringHelper
from io.jans.model.custom.script.type.auth import PersonAuthenticationType
from io.jans.fido2.client import Fido2ClientFactory
from io.jans.as.server.security import Identity
from io.jans.as.server.service import AuthenticationService, UserService, SessionIdService
from io.jans.as.server.util import ServerUtil
from io.jans.service.cdi.util import CdiUtil
from io.jans.util import StringHelper

from java.util.concurrent.locks import ReentrantLock
from javax.ws.rs import ClientErrorException
from javax.ws.rs.core import Response

import java
import sys
Expand Down Expand Up @@ -138,8 +134,8 @@ def prepareForStep(self, configurationAttributes, requestParameters, step):
elif (step == 2):
print "Fido2. Prepare for step 2"

session_id = CdiUtil.bean(SessionIdService).getSessionIdFromCookie()
if StringHelper.isEmpty(session_id):
session_id = CdiUtil.bean(SessionIdService).getSessionId()
if session_id == None:
print "Fido2. Prepare for step 2. Failed to determine session_id"
return False

Expand All @@ -164,7 +160,11 @@ def prepareForStep(self, configurationAttributes, requestParameters, step):
assertionService = Fido2ClientFactory.instance().createAssertionService(metaDataConfiguration)
assertionRequest = json.dumps({'username': userName}, separators=(',', ':'))
assertionResponse = assertionService.authenticate(assertionRequest).readEntity(java.lang.String)
except ClientResponseFailure, ex:
if "internal" in assertionResponse:
identity.setWorkingParameter("platformAuthenticatorAvailable", "true")
else:
identity.setWorkingParameter("platformAuthenticatorAvailable", "false")
except ClientErrorException, ex:
print "Fido2. Prepare for step 2. Failed to start assertion flow. Exception:", sys.exc_info()[1]
return False
else:
Expand All @@ -174,7 +174,7 @@ def prepareForStep(self, configurationAttributes, requestParameters, step):
attestationService = Fido2ClientFactory.instance().createAttestationService(metaDataConfiguration)
attestationRequest = json.dumps({'username': userName, 'displayName': userName}, separators=(',', ':'))
attestationResponse = attestationService.register(attestationRequest).readEntity(java.lang.String)
except ClientResponseFailure, ex:
except ClientErrorException, ex:
print "Fido2. Prepare for step 2. Failed to start attestation flow. Exception:", sys.exc_info()[1]
return False

Expand Down Expand Up @@ -227,18 +227,11 @@ def getMetaDataConfiguration(self):
try:
self.metaDataConfiguration = metaDataConfigurationService.getMetadataConfiguration().readEntity(java.lang.String)
return self.metaDataConfiguration
except ClientResponseFailure, ex:
except ClientErrorException, ex:
# Detect if last try or we still get Service Unavailable HTTP error
if (attempt == max_attempts) or (ex.getResponse().getResponseStatus() != Response.Status.SERVICE_UNAVAILABLE):
raise ex

java.lang.Thread.sleep(3000)
print "Attempting to load metadata: %d" % attempt
except ResteasyClientException, ex:
# Detect if last try or we still get Service Unavailable HTTP error
if attempt == max_attempts:
raise ex

java.lang.Thread.sleep(3000)
print "Attempting to load metadata: %d" % attempt
finally:
Expand Down
40 changes: 20 additions & 20 deletions docker-jans-auth-server/libs/casa-external_otp.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# Based on oxAuth OtpExternalAuthenticator.py

# Requires the following custom properties and values:
# otp_type: totp/hotp
# issuer: Gluu Inc
Expand All @@ -10,9 +8,6 @@
# qr_options: { width: 400, height: 400 }
# registration_uri: https://ce-dev.gluu.org/identity/register

import jarray
import json
import sys
from com.google.common.io import BaseEncoding
from com.lochbridge.oath.otp import HOTP
from com.lochbridge.oath.otp import HOTPValidator
Expand All @@ -21,18 +16,23 @@
from com.lochbridge.oath.otp.keyprovisioning import OTPAuthURIBuilder
from com.lochbridge.oath.otp.keyprovisioning import OTPKey
from com.lochbridge.oath.otp.keyprovisioning.OTPKey import OTPType

from io.jans.jsf2.message import FacesMessages
from io.jans.model.custom.script.type.auth import PersonAuthenticationType
from io.jans.as.server.security import Identity
from io.jans.as.server.service import AuthenticationService, UserService, SessionIdService
from io.jans.as.server.util import ServerUtil
from io.jans.service.cdi.util import CdiUtil
from io.jans.util import StringHelper

from java.security import SecureRandom
from java.util import Arrays
from java.util.concurrent import TimeUnit
from javax.faces.application import FacesMessage
from org.gluu.jsf2.message import FacesMessages
from org.gluu.model.custom.script.type.auth import PersonAuthenticationType
from org.gluu.oxauth.security import Identity
from org.gluu.oxauth.service import AuthenticationService, UserService, SessionIdService
from org.gluu.oxauth.util import ServerUtil
from org.gluu.service.cdi.util import CdiUtil
from org.gluu.util import StringHelper

import jarray
import json
import sys

class PersonAuthentication(PersonAuthenticationType):
def __init__(self, currentTimeMillis):
Expand Down Expand Up @@ -351,12 +351,12 @@ def findEnrollments(self, user_name, otpType, skipPrefix = True):
result = []

userService = CdiUtil.bean(UserService)
user = userService.getUser(user_name, "oxExternalUid")
user = userService.getUser(user_name, "jansExtUid")
if user == None:
print "OTP. Find enrollments. Failed to find user"
return result

user_custom_ext_attribute = userService.getCustomAttribute(user, "oxExternalUid")
user_custom_ext_attribute = userService.getCustomAttribute(user, "jansExtUid")
if user_custom_ext_attribute == None:
return result

Expand All @@ -377,8 +377,8 @@ def findEnrollments(self, user_name, otpType, skipPrefix = True):
return result

def validateSessionId(self, identity):
session_id = CdiUtil.bean(SessionIdService).getSessionIdFromCookie()
if StringHelper.isEmpty(session_id):
session_id = CdiUtil.bean(SessionIdService).getSessionId()
if session_id == None:
print "OTP. Validate session id. Failed to determine session_id"
return False

Expand Down Expand Up @@ -420,7 +420,7 @@ def processOtpAuthentication(self, requestParameters, user_name, identity, otp_a
otp_user_external_uid = "hotp:%s;%s" % ( otp_secret_key_encoded, validation_result["movingFactor"] )

# Add otp_user_external_uid to user's external GUID list
find_user_by_external_uid = userService.addUserAttribute(user_name, "oxExternalUid", otp_user_external_uid, True)
find_user_by_external_uid = userService.addUserAttribute(user_name, "jansExtUid", otp_user_external_uid, True)
if find_user_by_external_uid != None:
return True

Expand All @@ -433,7 +433,7 @@ def processOtpAuthentication(self, requestParameters, user_name, identity, otp_a
otp_user_external_uid = "totp:%s" % otp_secret_key_encoded

# Add otp_user_external_uid to user's external GUID list
find_user_by_external_uid = userService.addUserAttribute(user_name, "oxExternalUid", otp_user_external_uid, True)
find_user_by_external_uid = userService.addUserAttribute(user_name, "jansExtUid", otp_user_external_uid, True)
if find_user_by_external_uid != None:
return True

Expand Down Expand Up @@ -465,7 +465,7 @@ def processOtpAuthentication(self, requestParameters, user_name, identity, otp_a
new_otp_user_external_uid = "hotp:%s;%s" % ( otp_secret_key_encoded, validation_result["movingFactor"] )

# Update moving factor in user entry
find_user_by_external_uid = userService.replaceUserAttribute(user_name, "oxExternalUid", otp_user_external_uid, new_otp_user_external_uid, True)
find_user_by_external_uid = userService.replaceUserAttribute(user_name, "jansExtUid", otp_user_external_uid, new_otp_user_external_uid, True)
if find_user_by_external_uid != None:
return True

Expand Down Expand Up @@ -580,7 +580,7 @@ def hasEnrollments(self, configurationAttributes, user):

# Both hotp and totp are accounted
hasEnrollments = False
values = user.getAttributeValues("oxExternalUid")
values = user.getAttributeValues("jansExtUid")

if values != None:
for extUid in values:
Expand Down
Loading

0 comments on commit 089a872

Please sign in to comment.