diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/acr_router/Readme.txt b/docs/script-catalog/person_authentication/other/acr_router/Readme.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/acr_router/Readme.txt rename to docs/script-catalog/person_authentication/other/acr_router/Readme.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/allowed_countries/readme.txt b/docs/script-catalog/person_authentication/other/allowed_countries/readme.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/allowed_countries/readme.txt rename to docs/script-catalog/person_authentication/other/allowed_countries/readme.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.client_group/README.txt b/docs/script-catalog/person_authentication/other/basic.client_group/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.client_group/README.txt rename to docs/script-catalog/person_authentication/other/basic.client_group/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.external_logout/README.txt b/docs/script-catalog/person_authentication/other/basic.external_logout/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.external_logout/README.txt rename to docs/script-catalog/person_authentication/other/basic.external_logout/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.lock.account/README.txt b/docs/script-catalog/person_authentication/other/basic.lock.account/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.lock.account/README.txt rename to docs/script-catalog/person_authentication/other/basic.lock.account/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_auth_conf/INSTALLATION.txt b/docs/script-catalog/person_authentication/other/basic.multi_auth_conf/INSTALLATION.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_auth_conf/INSTALLATION.txt rename to docs/script-catalog/person_authentication/other/basic.multi_auth_conf/INSTALLATION.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_auth_conf/README.txt b/docs/script-catalog/person_authentication/other/basic.multi_auth_conf/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_auth_conf/README.txt rename to docs/script-catalog/person_authentication/other/basic.multi_auth_conf/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_login/INSTALLATION.txt b/docs/script-catalog/person_authentication/other/basic.multi_login/INSTALLATION.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_login/INSTALLATION.txt rename to docs/script-catalog/person_authentication/other/basic.multi_login/INSTALLATION.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_login/README.txt b/docs/script-catalog/person_authentication/other/basic.multi_login/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_login/README.txt rename to docs/script-catalog/person_authentication/other/basic.multi_login/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multiple_test_email_addresses/README.txt b/docs/script-catalog/person_authentication/other/basic.multiple_test_email_addresses/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multiple_test_email_addresses/README.txt rename to docs/script-catalog/person_authentication/other/basic.multiple_test_email_addresses/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.one_session/README.txt b/docs/script-catalog/person_authentication/other/basic.one_session/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.one_session/README.txt rename to docs/script-catalog/person_authentication/other/basic.one_session/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.reset_to_step/README.txt b/docs/script-catalog/person_authentication/other/basic.reset_to_step/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.reset_to_step/README.txt rename to docs/script-catalog/person_authentication/other/basic.reset_to_step/README.txt diff --git a/docs/script-catalog/person_authentication/other/bioid/README.txt b/docs/script-catalog/person_authentication/other/bioid/README.txt new file mode 100644 index 00000000000..6d988c5d079 --- /dev/null +++ b/docs/script-catalog/person_authentication/other/bioid/README.txt @@ -0,0 +1,72 @@ +# BioID Web Service +## Overview +[BioID Web Service](https://www.bioid.com) is a "Biometrics as a service" provider. This document will explain how to use Gluu's [BioID interception script](https://github.com/GluuFederation/oxAuth/blob/master/Server/integrations/bioID/BioIDExternalAuthenticator.py) to configure the Gluu Server for a two-step authentication process with username and password as the first step, and BioID's biometric authentication as the second step. + +In order to use this authentication mechanism your organization will need to register for a BioID account. + +## Prerequisitesm +- A Gluu Server ([installation instructions](../installation-guide/index.md)); +- [BioID interception script](https://github.com/GluuFederation/oxAuth/blob/master/Server/integrations/bioID/BioIDExternalAuthenticator.py) (included in the default Gluu Server distribution); +- An account with [BioID](https://bwsportal.bioid.com/register). + +## Properties +The mandatory properties in the BioID authentication script are as follows +| Property | Description | Example | +|-----------------------|-------------------------------|---------------| +|ENDPOINT |URL of the BioID Web Service|`https://bws.bioid.com/extension/`| +|APP_IDENTIFIER |API key |`c20b04cc-776a-45ed-7a1f-06347f8edf6c`| +|APP_SECRET |API secret |`sTGB4n4HAkvc2BnJp6KeNUTk`| +|STORAGE |The storage name assigned by BioID depending on the type of contract you have. |`bws`| +|PARTITION |A number assigned to your company by BioID. |`12345`| + + + +## Configure BioID Account + +1. [Sign up](https://bwsportal.bioid.com/register) for a BioID account. + +2. Upon registration, you will recieve an email with the instance name (listed as STORAGE in Gluu's BioID authentication script), partition number(listed as PARTITION in Gluu's BioID authentication script). + +3. As the owner of this instance, you are entitled to access BWS Portal at https://bwsportal.bioid.com using the account associated with your email. +With the BWS Portal, you can do the following: +a. View your trial information such as your credentials (e.g. your client certificate), enrolled classes, BWS logs and more. +b. Create your App ID and App secret, under "Web API keys". + +## BioID Documentation + +You can find all API reference at https://developer.bioid.com/bwsreference. +Lots of useful information about BWS is available at https://developer.bioid.com/blog. +If you intend to use liveness detection, you will find information about motion trigger helpful: https://developer.bioid.com/app-developer-guide/bioid-motion-detection + +## Configure oxTrust + +Follow the steps below to configure the BioID module in the oxTrust Admin GUI. + +1. Navigate to `Configuration` > `Person Authentication Scripts`. +1. Scroll down to the BioID authentication script +![bioid-script](../img/admin-guide/multi-factor/bioid-script.png) + +1. Configure the properties, all of which are mandatory, according to your API + +1. Enable the script by ticking the check box +![enable](../img/admin-guide/enable.png) + +Now BioID's biometric authentication is available as an authentication mechanism for your Gluu Server. This means that, using OpenID Connect `acr_values`, applications can now request BioID biometric authentication for users. + +!!! Note + To make sure BioID has been enabled successfully, you can check your Gluu Server's OpenID Connect configuration by navigating to the following URL: `https:///.well-known/openid-configuration`. Find `"acr_values_supported":` and you should see `"bioid"`. + +## Make BioID the Default Authentication Mechanism + +Now applications can request BioID's biometric authentication. To make BioID biometic authentication your default authentication mechanism, follow these instructions: + +1. Navigate to `Configuration` > `Manage Authentication`. +2. Select the `Default Authentication Method` tab. +3. In the Default Authentication Method window you will see two options: `Default acr` and `oxTrust acr`. + + - The `oxTrust acr` field controls the authentication mechanism that is presented to access the oxTrust dashboard GUI (the application you are in). + - The `Default acr` field controls the default authentication mechanism that is presented to users from all applications that leverage your Gluu Server for authentication. + +You can change one or both fields to BioID authentication as you see fit. If you want BioID to be the default authentication mechanism for access to oxTrust and all other applications that leverage your Gluu Server, change both fields to bioid. + +![BioID](../img/admin-guide/multi-factor/bioID.png) diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/cert/Generate certs guide.md b/docs/script-catalog/person_authentication/other/cert/Generate certs guide.md similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/cert/Generate certs guide.md rename to docs/script-catalog/person_authentication/other/cert/Generate certs guide.md diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/cert/Generate certs without configs.md b/docs/script-catalog/person_authentication/other/cert/Generate certs without configs.md similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/cert/Generate certs without configs.md rename to docs/script-catalog/person_authentication/other/cert/Generate certs without configs.md diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/cert/Quick certs guide for testing.md b/docs/script-catalog/person_authentication/other/cert/Quick certs guide for testing.md similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/cert/Quick certs guide for testing.md rename to docs/script-catalog/person_authentication/other/cert/Quick certs guide for testing.md diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/cert/README.txt b/docs/script-catalog/person_authentication/other/cert/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/cert/README.txt rename to docs/script-catalog/person_authentication/other/cert/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/compromised_password/readme.txt b/docs/script-catalog/person_authentication/other/compromised_password/readme.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/compromised_password/readme.txt rename to docs/script-catalog/person_authentication/other/compromised_password/readme.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/duo/README.txt b/docs/script-catalog/person_authentication/other/duo/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/duo/README.txt rename to docs/script-catalog/person_authentication/other/duo/README.txt diff --git a/docs/script-catalog/person_authentication/other/forgot_password/README.md b/docs/script-catalog/person_authentication/other/forgot_password/README.md deleted file mode 100644 index 82fef8bed4a..00000000000 --- a/docs/script-catalog/person_authentication/other/forgot_password/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Forgot Password 2FA Token Interception Script - -## Description - -This script is a 2 in 1. It can be used to enable user to reset its password **or** to enable 2FA sending a token to user's email : - -How they work: - -### Forgot Password -* Step 1: User enters e-mail and if e-mail exists, user receive a token via email -* Step 2: User enters token received by e-mail -* Step 3: User enters new password - -### Emai 2FA -* Step 1: User enters username and password -* Step 2: User enters token received by e-mail - -## Instalation - -* Make sure you have your **SMTP settings correctly Gluu Server** - Navigate to Configuration > Organization Configuration > SMTP Server Configuration -* Set up the script function (Forgot Password or Email 2FA) - Navigate to Configuration > Manage Custom Scripts, choose the script and set a **custom attribute** with key `SCRIPT_FUNCTION` and value `forgot_password` for Forgot Password mode, or `email_2FA` for Email 2FA mode. -* Enable the custom script. - -Please notice the xhtml files for this script are currently located at `oxAuth/Server/src/main/webapp/auth/forgot_password/` - -Note: If you want to use both scripts, you'll need to copy it and change the **custom attribute** from the copied script. diff --git a/docs/script-catalog/person_authentication/other/forgot_password/forgot_password.py b/docs/script-catalog/person_authentication/other/forgot_password/forgot_password.py deleted file mode 100644 index 7a4d3856e47..00000000000 --- a/docs/script-catalog/person_authentication/other/forgot_password/forgot_password.py +++ /dev/null @@ -1,435 +0,0 @@ -# coding: utf-8 -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Christian Eland - - -from org.xdi.oxauth.service import AuthenticationService -from io.jans.as.server.service import UserService -from org.gluu.oxauth.auth import Authenticator -from org.xdi.oxauth.security import Identity -from org.xdi.model.custom.script.type.auth import PersonAuthenticationType -from org.xdi.service.cdi.util import CdiUtil -from org.xdi.util import StringHelper -from org.xdi.oxauth.util import ServerUtil -from io.jans.as.common.service.common import ConfigurationService -from io.jans.as.common.service.common import EncryptionService -from io.jans.jsf2.message import FacesMessages -from jakarta.faces.application import FacesMessage -from io.jans.orm.exception import AuthenticationException - -#dealing with smtp server -import smtplib - -#dealing with emails -from email.mime.multipart import MIMEMultipart -from email.mime.text import MIMEText - -# This one is from core Java -from java.util import Arrays - -# to generate string token -import random -import string - -# regex -import re - -import urllib - -import java - -class EmailValidator(): - ''' - Class to check e-mail format - ''' - regex = '^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$' - - def check(self, email): - ''' - Check if email format is valid - returns: boolean - ''' - - if(re.search(self.regex,email)): - print "Forgot Password - %s is a valid email format" % email - return True - else: - print "Forgot Password - %s is an invalid email format" % email - return False - -class Token: - #class that deals with string token - - def generateToken(self): - ''' method to generate token string - returns: String - ''' - letters = string.ascii_lowercase - - #token lenght - lenght = 20 - - #generate token - token = ''.join(random.choice(letters) for i in range(lenght)) - print "Forgot Password - Generating token" - - return token - - -class EmailSender(): - #class that sends e-mail through smtp - - def getSmtpConfig(self): - ''' - get SMTP config from Gluu Server - return dict - ''' - - smtpconfig = CdiUtil.bean(ConfigurationService).getConfiguration().getSmtpConfiguration() - - if smtpconfig is None: - print "Forgot Password - SMTP CONFIG DOESN'T EXIST - Please configure" - - else: - print "Forgot Password - SMTP CONFIG FOUND" - encryptionService = CdiUtil.bean(EncryptionService) - smtp_config = { - 'host' : smtpconfig.getHost(), - 'port' : smtpconfig.getPort(), - 'user' : smtpconfig.getUserName(), - 'from' : smtpconfig.getFromEmailAddress(), - 'pwd_decrypted' : encryptionService.decrypt(smtpconfig.getPassword()), - 'req_ssl' : smtpconfig.isRequiresSsl(), - 'requires_authentication' : smtpconfig.isRequiresAuthentication(), - 'server_trust' : smtpconfig.isServerTrust() - } - - return smtp_config - - - - def sendEmail(self,useremail,token): - ''' - send token by e-mail to useremail - ''' - - # server connection - smtpconfig = self.getSmtpConfig() - - try: - s = smtplib.SMTP(smtpconfig['host'], port=smtpconfig['port']) - - - if smtpconfig['requires_authentication']: - - if smtpconfig['req_ssl']: - s.starttls() - - s.login(smtpconfig['user'], smtpconfig['pwd_decrypted']) - - - #message setup - msg = MIMEMultipart() #create message - - message = "Here is your token: %s" % token - - msg['From'] = smtpconfig['from'] #sender - msg['To'] = useremail #recipient - msg['Subject'] = "Password Reset Request" #subject - - #attach message body - msg.attach(MIMEText(message, 'plain')) - - #send message via smtp server - # send_message method is for python3 only s.send_message(msg) - - #send email (python2) - s.sendmail(msg['From'],msg['To'],msg.as_string()) - - #after sent, delete - del msg - - except smtplib.SMTPAuthenticationError as err: - print "Forgot Password - SMTPAuthenticationError - %s - %s" % (MY_ADDRESS,PASSWORD) - print err - - except smtplib.smtplib.SMTPSenderRefused as err: - print "Forgot Password - SMTPSenderRefused - " + err - - -class PersonAuthentication(PersonAuthenticationType): - - - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - - print "Forgot Password - Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Forgot Password - Destroyed successfully" - return True - - def getApiVersion(self): - # I'm not sure why is 11 and not 2 - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - ''' - Authenticates user - Step 1 will be defined according to SCRIPT_FUNCTION custom attribute - returns: boolean - ''' - - #gets custom attribute - sf = configurationAttributes.get("SCRIPT_FUNCTION").getValue2() - - print "Forgot Password - %s - Authenticate for step %s" % (sf, step) - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - - if step == 1: - - if sf == "forgot_password": - - - authenticationService = CdiUtil.bean(AuthenticationService) - - logged_in = authenticationService.authenticate(user_name, user_password) - - - if not logged_in: - - - email = ServerUtil.getFirstValue(requestParameters, "ForgotPasswordForm:useremail") - validator = EmailValidator() - if not validator.check(email): - print "Forgot Password - Email format invalid" - return False - - else: - print "Forgot Password -Email format valid" - - print "Forgot Password - Entered email is %s" % email - identity.setWorkingParameter("useremail",email) - - # Just trying to get the user by the email - user_service = CdiUtil.bean(UserService) - user2 = user_service.getUserByAttribute("mail", email) - - if user2 is not None: - - print user2 - print "Forgot Password - User with e-mail %s found." % user2.getAttribute("mail") - - # send email - new_token = Token() - token = new_token.generateToken() - sender = EmailSender() - print "Email: " + email - print "Token: " + token - sender.sendEmail(email,token) - - - identity.setWorkingParameter("token", token) - print identity.getWorkingParameter("token") - - - - else: - print "Forgot Password - User with e-mail %s not found" % email - - return True - - - else: - # if user is already authenticated, returns true. - - user = authenticationService.getAuthenticatedUser() - print "Forgot Password - User %s is authenticated" % user.getUserId() - - return True - - if sf == "email_2FA": - - try: - # Just trying to get the user by the uid - authenticationService = CdiUtil.bean(AuthenticationService) - logged_in = authenticationService.authenticate(user_name, user_password) - - print 'email_2FA user_name: ' + str(user_name) - - user_service = CdiUtil.bean(UserService) - user2 = user_service.getUserByAttribute("uid", user_name) - - if user2 is not None: - print "user:" - print user2 - print "Forgot Password - User with e-mail %s found." % user2.getAttribute("mail") - email = user2.getAttribute("mail") - uid = user2.getAttribute("uid") - - # send token - # send email - new_token = Token() - token = new_token.generateToken() - sender = EmailSender() - print "Email: " + email - print "Token: " + token - sender.sendEmail(email,token) - - identity.setWorkingParameter("token", token) - - return True - - except AuthenticationException as err: - print err - return False - - - - - if step == 2: - # step 2 user enters token - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - authenticationService = CdiUtil.bean(AuthenticationService) - logged_in = authenticationService.authenticate(user_name, user_password) - - # retrieves token typed by user - input_token = ServerUtil.getFirstValue(requestParameters, "ResetTokenForm:inputToken") - - print "Forgot Password - Token inputed by user is %s" % input_token - - token = identity.getWorkingParameter("token") - print "Forgot Password - Retrieved token" - email = identity.getWorkingParameter("useremail") - print "Forgot Password - Retrieved email" - - # compares token sent and token entered by user - if input_token == token: - print "Forgot Password - token entered correctly" - identity.setWorkingParameter("token_valid", True) - - return True - - else: - print "Forgot Password - wrong token" - return False - - - if step == 3: - # step 3 enters new password (only runs if custom attibute is forgot_password - - user_service = CdiUtil.bean(UserService) - - email = identity.getWorkingParameter("useremail") - user2 = user_service.getUserByAttribute("mail", email) - - - user_name = user2.getUserId() - - new_password = ServerUtil.getFirstValue(requestParameters, "UpdatePasswordForm:newPassword") - - print "Forgot Password - New password submited" - - # update user info with new password - user2.setAttribute("userPassword",new_password) - print "Forgot Password - user uid is %s" % user_name - print "Forgot Password - Updating user with new password..." - user_service.updateUser(user2) - print "Forgot Password - User updated with new password" - # authenticates and login user - print "Forgot Password - Loading authentication service..." - authenticationService2 = CdiUtil.bean(AuthenticationService) - - print "Forgot Password - Trying to authenticate user..." - login = authenticationService2.authenticate(user_name, new_password) - - return True - - def prepareForStep(self, configurationAttributes, requestParameters, step): - - print "Forgot Password - Preparing for step %s" % step - - return True - - - # Return value is a java.util.List - def getExtraParametersForStep(self, configurationAttributes, step): - return Arrays.asList("token","useremail","token_valid") - - - # This method determines how many steps the authentication flow may have - # It doesn't have to be a constant value - def getCountAuthenticationSteps(self, configurationAttributes): - - sf = configurationAttributes.get("SCRIPT_FUNCTION").getValue2() - - - # if option is forgot_token - if sf == "forgot_password": - print "Entered sf == forgot_password" - return 3 - - # if ption is email_2FA - if sf == "email_2FA": - print "Entered if sf=email_2FA" - return 2 - - else: - print "Forgot Password - Custom Script Custom Property Incorrect, please check" - - - # The xhtml page to render upon each step of the flow - # returns a string relative to oxAuth webapp root - def getPageForStep(self, configurationAttributes, step): - - sf = configurationAttributes.get("SCRIPT_FUNCTION").getValue2() - - if step == 1: - - if sf == "forgot_password": - return "/auth/forgot_password/forgot.xhtml" - - if sf == 'email_2FA': - return "" - - if step == 2: - return "/auth/forgot_password/entertoken.xhtml" - - if step == 3: - if sf == "forgot_password": - return "/auth/forgot_password/newpassword.xhtml" - - - def getNextStep(self, configurationAttributes, requestParameters, step): - # Method used on version 2 (11?) - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/fortinet/README.txt b/docs/script-catalog/person_authentication/other/fortinet/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/fortinet/README.txt rename to docs/script-catalog/person_authentication/other/fortinet/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/README.txt b/docs/script-catalog/person_authentication/other/gplus/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/README.txt rename to docs/script-catalog/person_authentication/other/gplus/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/README_idfirst.md b/docs/script-catalog/person_authentication/other/idfirst/README_idfirst.md similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/README_idfirst.md rename to docs/script-catalog/person_authentication/other/idfirst/README_idfirst.md diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/documentation/README.txt b/docs/script-catalog/person_authentication/other/obconnect/documentation/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/documentation/README.txt rename to docs/script-catalog/person_authentication/other/obconnect/documentation/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/documentation/larger_picture.png b/docs/script-catalog/person_authentication/other/obconnect/documentation/larger_picture.png similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/documentation/larger_picture.png rename to docs/script-catalog/person_authentication/other/obconnect/documentation/larger_picture.png diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/registration/read.txt b/docs/script-catalog/person_authentication/other/registration/read.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/registration/read.txt rename to docs/script-catalog/person_authentication/other/registration/read.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/INSTALLATION.txt b/docs/script-catalog/person_authentication/other/saml/INSTALLATION.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/INSTALLATION.txt rename to docs/script-catalog/person_authentication/other/saml/INSTALLATION.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/README.txt b/docs/script-catalog/person_authentication/other/saml/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/README.txt rename to docs/script-catalog/person_authentication/other/saml/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/twilio_sms/README.txt b/docs/script-catalog/person_authentication/other/twilio_sms/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/twilio_sms/README.txt rename to docs/script-catalog/person_authentication/other/twilio_sms/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/Properties description.md b/docs/script-catalog/person_authentication/other/uaf/Properties description.md similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/Properties description.md rename to docs/script-catalog/person_authentication/other/uaf/Properties description.md diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/INSTALLATION.md b/docs/script-catalog/person_authentication/other/wwpass/INSTALLATION.md similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/INSTALLATION.md rename to docs/script-catalog/person_authentication/other/wwpass/INSTALLATION.md diff --git a/docs/script-catalog/person_authentication/other/wwpass/README.md b/docs/script-catalog/person_authentication/other/wwpass/README.md index 59e1f770fe4..62b46b60745 100644 --- a/docs/script-catalog/person_authentication/other/wwpass/README.md +++ b/docs/script-catalog/person_authentication/other/wwpass/README.md @@ -1,6 +1,4 @@ -# Setting Up WWPass Authentication in Gluu Server - -## Introduction +# WWPass integration for Gluu [WWPass](https://wwpass.com/) replaces the traditional username and password login with a more advanced multi-factor authentication solution. WWPass employs @@ -10,235 +8,12 @@ starts with a smartphone app or a hardware token as the first authentication factor. Then additional authentication factors such as PIN or biometrics can be added to verify the user identity further. -[Gluu Server](https://gluu.org/docs/gluu-server/4.1/) is a container -distribution of free open source software (FOSS) for identity and access -management (IAM). Gluu Server combines SAML 2.0, LDAP, OpenID Connect, -and other authentication and authorization protocol implementations to create -a platform for user authentication, identity information, and policy decisions. - -Combining WWPass strong multi-factor authentication with the versatility of -Gluu Server helps to build secure IAM solutions that can be used for single -sign-on (SSO), customer identity and access management (CIAM), and identity -federation. - -## Prerequisites - -This tutorial assumes that you have the following: - -- Gluu Server 4.1.1 installed on Ubuntu Server 18.04 or 16.04; -- An administrative account on this Ubuntu Server; -- An application certificate and private key for WWPass authentication; -- WWPass Key app or hardware token; - -### Obtain Application Certificate and Private Key From WWPass - -To obtain an application certificate and private key go to -[wwpass.com](https://wwpass.com), click **Sign Up** to create a developer -account or **Log In** if you already have an account. Then follow the website -instructions to register your application domain and issue the application -certificate. - -## Prepare WWPass Integration Files - -Copy this directory to your Gluu server and make it current -```console -cd wwpass -``` - -Files in `pages` directory should be deployed to -`/opt/gluu-server/opt/gluu/jetty/oxauth/custom/pages/` - -```console -sudo cp -rL pages/* /opt/gluu-server/opt/gluu/jetty/oxauth/custom/pages/ -``` - -Files in `static` directory should be deployed to -`/opt/gluu-server/opt/gluu/jetty/oxauth/custom/static/` - -```console -sudo cp -rL pages/* /opt/gluu-server/opt/gluu/jetty/oxauth/custom/static/ -``` - -Copy `wwpass.py` to `/opt/gluu-server/opt/gluu/python/libs/` - -```console -sudo cp wwpass.py /opt/gluu-server/opt/gluu/python/libs/ -``` - -Copy `ticket.json` to `/opt/gluu-server/opt/wwpass_gluu/cgi` - -``` console -sudo mkdir -p /opt/gluu-server/opt/wwpass_gluu/cgi -sudo cp ticket.json /opt/gluu-server/opt/wwpass_gluu/cgi -``` - -Make sure `ticket.json` is executable - -```console -sudo chmod 755 /opt/gluu-server/opt/wwpass_gluu/cgi/ticket.json -``` - -Copy WWPass application certificate and private key to -`/opt/gluu-server/opt/wwpass_gluu/` -(assuming the certificate and key files are in your home directory) - -```console -sudo cp ~/gluu_client.crt /opt/gluu-server/opt/wwpass_gluu/gluu_client.crt -sudo cp ~/gluu_client.key /opt/gluu-server/opt/wwpass_gluu/gluu_client.key -``` - -Replace `~/gluu_client.crt` and `~/gluu_client.key` with the names and location -of your certificate and key files. - -Copy WWPass CA certificate `wwpass.ca.crt` to `/opt/gluu-server/opt/wwpass_gluu/` - -```console -sudo cp wwpass.ca.crt /opt/gluu-server/opt/wwpass_gluu -``` - -Log in to the Gluu Server container - -```console -sudo /sbin/gluu-serverd login -``` - -Change ownership of files and directories just copied - -```console -chown -R jetty:jetty /opt/jetty -chown root:gluu /opt/gluu/python/libs/wwpass.py -``` - -## Configure Apache - -Use your favorite console text editor to change Apache configuration - -```console -[vi|nano|joe|...] /opt/gluu-server/etc/apache2/sites-available/https_gluu.conf -``` - -Scroll down the file until you find the last `...` tag and -insert the following snippet below it: - -```apache - - require all granted - - -ScriptAlias "/wwpass/" "/opt/wwpass_gluu/cgi/" - - - SetHandler cgi-script - Options +ExecCGI - Order deny,allow - Allow from all - -``` - -Save the file and exit the editor. - -Enable mod_cgi and restart apache: - -```console -a2enmod cgi -systemctl restart apache2 -``` - -Check that `ticket.json` is working. -Go to `https:///wwpass/ticket.json`. -If your setup is correct, you will see output like this: - -```json -{"result": true, "data": "SPNAME:07629a1963c5e4f4f339ecb852b7a0bf10a90c62@p-sp-05-50:16033", "ttl": 600, "encoding": "plain"} -``` - -## Configure Gluu Server - -Log in as administrator and go to "Configuration -> Manage Custom scripts". - -In `Person Authentication` tab, click `Add custom script configuration` at the bottom of the page - -Create custom script `wwpass` with Location Type set to `Database`. - -Add the following to `Custom Property` fields by clicking on `Add new property` button: - -- wwpass_crt_file: /opt/wwpass_gluu/gluu_client.crt -- wwpass_key_file: /opt/wwpass_gluu/gluu_client.key -- registration_url: URL of the registration web application, if you have one. Do not add this property otherwise -- recovery_url: URL for account recovery, if you have one. Do not add this property otherwise. - -To require PIN or biometrics during login, add: - -- use_pin: True - -To enable binding WWPass keys with email, add: - -- allow_email_bind: True - -Note, your Gluu server should be able to send emails, see -`Configuration -> Organization configuration -> SMTP Server Configuration`. - -To enable binding WWPass keys with existing usernames and passwords, add: - -- allow_password_bind: True - -To enable binding WWPass keys with another WWPass key, add: - -- allow_passkey_bind: True - -Replace the content of `Script` textbox with the content of `wwpassauth.py` from `gluu-master` - -Set `Enabled` checkbox to enable the custom script: - -Click the `Update` button. - -It's also recommended to increase the unauthenticated session lifetime to give -users more time to bind their WWPass keys. - -Go to `Configuration -> JSON configuration -> OxAuth Configuration`, find -`sessionIdUnauthenticatedUnusedLifetime` setting and set it to `600` or more. - -Click `Update` to save settings. - -### Set up Authentication Method - -Before switching to WWPass authentication, make sure you have opened -an administrator session in a different browser (not in a different window, -but a completely different browser). Do not close that browser window and -reload it from time to time to make sure your session does not expire. - -Keep the backup session opened until you are sure that WWPass authentication -works properly or you might lock yourself out of Gluu. If that happens, refer to: -[Gluu FAQ](https://gluu.org/docs/gluu-server/operation/faq/#revert-an-authentication-method) - -In the Gluu Admin interface, navigate to `Configuration -> Manage Authentication -> Default Authentication Method`. -Set both options to "wwpass". - -Click `Update` to save settings. - -### Test Your Setup - -Open "https:///" in a different browser (not the one you used to -configure Gluu). - -Try to sign in to your Gluu server with WWPass and bind your key using either -email or username and password. - -If something does not work as expected, return to your main browser and revert -`Configuration -> Manage Authentication -> Default Authentication Method` back -to `auth_ldap_server` while you troubleshoot the problem. - -## Troubleshooting +## Installation -Relevant Gluu log files are: +To install WWPass support in Gluu server refer to [INSTALLATION.md](INSTALLATION.md). -- `/opt/gluu-server/opt/gluu/jetty/oxauth/logs/oxauth.log` -- `/opt/gluu-server/opt/gluu/jetty/oxauth/logs/oxauth_script.log` +To install additional components refer to main wwpass-gluu repository at https://github.com/wwpass/gluu -Check the files above for any errors. Errors in `wwpass` interception script -are also displayed in Gluu web interface at 'Configuration -> Manage Custom -scripts'. If there are any errors in the script, its name will be in red and -the script editor will display the red button named "Show Error". +## Contacts -Feel free to contact WWPass at support@wwpass.com if you have troubles -integrating WWPass in your Gluu Server. +Feel free to contact WWPass at support@wwpass.com if you have trouble integrating WWPass in your Gluu setup \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/yubicloud/README.txt b/docs/script-catalog/person_authentication/other/yubicloud/README.txt similarity index 100% rename from jans-linux-setup/jans_setup/static/extension/person_authentication/other/yubicloud/README.txt rename to docs/script-catalog/person_authentication/other/yubicloud/README.txt diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/README.md b/jans-linux-setup/jans_setup/static/extension/person_authentication/README.md deleted file mode 100644 index ef38c90e805..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# 2FA authentication scripts - -Jython files contained in the top level of this folder are already added as authentication scripts in your Janssen installation. - -Inside `other` directory you may find extra information about these scripts as well as additional (non curated) scripts that you may use as a guide to integrate third party authentication services or APIs with Janssen server. \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/acr_router/acr_routerauthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/acr_router/acr_routerauthenticator.py deleted file mode 100644 index 74526837884..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/acr_router/acr_routerauthenticator.py +++ /dev/null @@ -1,84 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# -from __future__ import print_function -from io.jans.model.custom.script.type.auth import PersonAuthenticationType - - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - """ - Args: - currentTimeMillis (int): current time in miliseconds - """ - self.currentTimeMillis = currentTimeMillis - - @classmethod - def init(cls, customScript, configurationAttributes): - print("ACR Router. Initialization") - if not configurationAttributes.containsKey("new_acr_value"): - print("ACR Router. Initialization. Property acr_router_value is mandatory") - return False - print("ACR Router. Initialized successfully") - return True - - @classmethod - def destroy(cls, configurationAttributes): - print("ACR Router. Destroy") - print("ACR Router. Destroyed successfully") - - return True - - @classmethod - def getAuthenticationMethodClaims(cls, requestParameters): - return None - - @classmethod - def getApiVersion(cls): - return 11 - - @classmethod - def isValidAuthenticationMethod(cls, usageType, configurationAttributes): - return False - - @classmethod - def getAlternativeAuthenticationMethod(cls, usageType, configurationAttributes): - print("ACR Router. get new acr value") - new_acr_value = configurationAttributes.get("new_acr_value").getValue2() - # Put your custom logic to determine if routing required here... - return new_acr_value - - @classmethod - def authenticate(cls, configurationAttributes, requestParameters, step): - return False - - @classmethod - def prepareForStep(cls, configurationAttributes, requestParameters, step): - return True - - @classmethod - def getExtraParametersForStep(cls, configurationAttributes, step): - return None - - @classmethod - def getCountAuthenticationSteps(cls, configurationAttributes): - return 1 - - @classmethod - def getPageForStep(cls, configurationAttributes, step): - return "" - - @classmethod - def getNextStep(cls, configurationAttributes, requestParameters, step): - return -1 - - @classmethod - def getLogoutExternalUrl(cls, configurationAttributes, requestParameters): - print("Get external logout URL call") - return None - - @classmethod - def logout(cls, configurationAttributes, requestParameters): - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/allowed_countries/allowed_countries.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/allowed_countries/allowed_countries.py deleted file mode 100644 index cc9779d3fef..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/allowed_countries/allowed_countries.py +++ /dev/null @@ -1,155 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from java.util import Arrays -from org.apache.http.params import CoreConnectionPNames -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from org.gluu.oxauth.model.config import ConfigurationFactory -from io.jans.as.server.service import UserService, AuthenticationService, SessionIdService -from io.jans.as.server.service.net import HttpService -from io.jans.as.server.util import ServerUtil -from io.jans.util import StringHelper -from io.jans.as.server.service.common import EncryptionService -from java.util import Arrays, HashMap, IdentityHashMap - -import java -import datetime -import urllib - -import sys -import json - - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic. Initialization" - self.allowedCountries = configurationAttributes.get("allowed_countries").getValue2() - print "Basic. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Basic. Destroy" - print "Basic. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - session_attributes = identity.getSessionId().getSessionAttributes() - authenticationService = CdiUtil.bean(AuthenticationService) - allowedCountriesListArray = StringHelper.split(self.allowedCountries, ",") - if (len(allowedCountriesListArray) > 0 and session_attributes.containsKey("remote_ip")): - remote_ip = session_attributes.get("remote_ip") - remote_loc_dic = self.determineGeolocationData(remote_ip) - if remote_loc_dic == None: - print "Super-Gluu. Prepare for step 2. Failed to determine remote location by remote IP '%s'" % remote_ip - return - remote_loc = "%s" % ( remote_loc_dic['countryCode']) - print "Your remote location is "+remote_loc - if remote_loc in allowedCountriesListArray: - print "you are allowed to access" - else: - return False - - - if (step == 1): - print "Basic. Authenticate for step 1" - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): - logged_in = authenticationService.authenticate(user_name, user_password) - - if (not logged_in): - return False - - return True - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "Basic. Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def logout(self, configurationAttributes, requestParameters): - return True - - def determineGeolocationData(self, remote_ip): - print "Super-Gluu. Determine remote location. remote_ip: '%s'" % remote_ip - httpService = CdiUtil.bean(HttpService) - http_client = httpService.getHttpsClient() - http_client_params = http_client.getParams() - http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15 * 1000) - geolocation_service_url = "http://ip-api.com/json/%s?fields=520191" % remote_ip - geolocation_service_headers = { "Accept" : "application/json" } - try: - http_service_response = httpService.executeGet(http_client, geolocation_service_url, geolocation_service_headers) - http_response = http_service_response.getHttpResponse() - except: - print "Super-Gluu. Determine remote location. Exception: ", sys.exc_info()[1] - return None - - try: - if not httpService.isResponseStastusCodeOk(http_response): - print "Super-Gluu. Determine remote location. Get invalid response from validation server: ", str(http_response.getStatusLine().getStatusCode()) - httpService.consume(http_response) - return None - response_bytes = httpService.getResponseContent(http_response) - response_string = httpService.convertEntityToString(response_bytes) - httpService.consume(http_response) - finally: - http_service_response.closeConnection() - - if response_string == None: - print "Super-Gluu. Determine remote location. Get empty response from location server" - return None - - - response = json.loads(response_string) - - if not StringHelper.equalsIgnoreCase(response['status'], "success"): - print "Super-Gluu. Determine remote location. Get response with status: '%s'" % response['status'] - return None - - return response - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/ConsentGatheringSample.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/ConsentGatheringSample.py deleted file mode 100644 index ac228de387f..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/ConsentGatheringSample.py +++ /dev/null @@ -1,87 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.authz import ConsentGatheringType -from io.jans.util import StringHelper - -import java -import random - -class ConsentGathering(ConsentGatheringType): - - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Consent-Gathering. Initializing ..." - print "Consent-Gathering. Initialized successfully" - - return True - - def destroy(self, configurationAttributes): - print "Consent-Gathering. Destroying ..." - print "Consent-Gathering. Destroyed successfully" - - return True - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def getApiVersion(self): - return 11 - - # Main consent-gather method. Must return True (if gathering performed successfully) or False (if fail). - # All user entered values can be access via Map context.getPageAttributes() - def authorize(self, step, context): # context is reference of io.jans.as.server.service.external.context.ConsentGatheringContext - print "Consent-Gathering. Authorizing..." - - if step == 1: - allowButton = context.getRequestParameters().get("authorizeForm:allowButton") - if (allowButton != None) and (len(allowButton) > 0): - print "Consent-Gathering. Authorization success for step 1" - return True - - print "Consent-Gathering. Authorization declined for step 1" - elif step == 2: - allowButton = context.getRequestParameters().get("authorizeForm:allowButton") - if (allowButton != None) and (len(allowButton) > 0): - print "Consent-Gathering. Authorization success for step 2" - return True - - print "Consent-Gathering. Authorization declined for step 2" - - return False - - def getNextStep(self, step, context): - return -1 - - def prepareForStep(self, step, context): - if not context.isAuthenticated(): - print "User is not authenticated. Aborting authorization flow ..." - return False - - if step == 2: - pageAttributes = context.getPageAttributes() - - # Generate random consent gathering request - consentRequest = "Requested transaction #%s approval for the amount of sum $ %s.00" % ( random.randint(100000, 1000000), random.randint(1, 100) ) - pageAttributes.put("consent_request", consentRequest) - return True - - return True - - def getStepsCount(self, context): - return 2 - - def getPageForStep(self, step, context): - if step == 1: - return "/authz/authorize.xhtml" - elif step == 2: - return "/authz/transaction.xhtml" - - return "" diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/docs/Authz design.dia b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/docs/Authz design.dia deleted file mode 100644 index 66b1837de32..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/docs/Authz design.dia and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/docs/Authz design.png b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/docs/Authz design.png deleted file mode 100644 index daf70a1d5dd..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/authz/docs/Authz design.png and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/azuread/AzureADAuthenticationForGluu.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/azuread/AzureADAuthenticationForGluu.py deleted file mode 100644 index ca3eee5f3e7..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/azuread/AzureADAuthenticationForGluu.py +++ /dev/null @@ -1,271 +0,0 @@ -# Author: Naveen Kumar Gopi - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import AuthenticationService, UserService -from org.gluu.oxauth.model.common import User -from io.jans.util import StringHelper, ArrayHelper -from java.util import IdentityHashMap -from org.apache.commons.codec.binary import Base64 -from java.lang import String -import httplib -import urllib -import json - -import java - - -class PersonAuthentication(PersonAuthenticationType): - - def __init__(self, current_time_millis): - self.currentTimeMillis = current_time_millis - - def init(self, customScript, configuration_attributes): - print "AzureAD. Initialization" - - global azure_tenant_id - azure_tenant_id = configuration_attributes.get("azure_tenant_id").getValue2() - print "AzureAD. Initialization. Value of azure_tenant_id is %s" % azure_tenant_id - - global azure_client_id - azure_client_id = configuration_attributes.get("azure_client_id").getValue2() - print "AzureAD. Initialization. Value of azure_client_id is %s" % azure_client_id - - global azure_client_secret - azure_client_secret = configuration_attributes.get("azure_client_secret").getValue2() - - global MICROSOFT_AUTHORITY_URL - MICROSOFT_AUTHORITY_URL = 'login.microsoftonline.com' - - global AZURE_AD_GRAPH_RESOURCE_ENDPOINT - AZURE_AD_GRAPH_RESOURCE_ENDPOINT = 'https://graph.windows.net' - - global azure_user_uuid - azure_user_uuid = "oid" - - global gluu_ldap_uuid - gluu_ldap_uuid = "uid" - - global ADMIN - ADMIN = 'admin' - - global attributes_mapping - - if (configuration_attributes.containsKey("azure_ad_attributes_list") and - configuration_attributes.containsKey("gluu_ldap_attributes_list")): - - azure_ad_attributes_list = configuration_attributes.get("azure_ad_attributes_list").getValue2() - if StringHelper.isEmpty(azure_ad_attributes_list): - print "AzureAD: Initialization. The property azure_ad_attributes_list is empty" - return False - - gluu_ldap_attributes_list = configuration_attributes.get("gluu_ldap_attributes_list").getValue2() - if StringHelper.isEmpty(gluu_ldap_attributes_list): - print "AzureAD: Initialization. The property gluu_ldap_attributes_list is empty" - return False - - attributes_mapping = self.attribute_mapping_function(azure_ad_attributes_list, gluu_ldap_attributes_list) - if attributes_mapping is None: - print "AzureAD: Initialization. The attributes mapping isn't valid" - return False - - print "AzureAD. Initialized successfully" - return True - - @staticmethod - def attribute_mapping_function(azure_ad_attributes_list, gluu_ldap_attributes_list): - try: - azure_ad_attributes_list_array = StringHelper.split(azure_ad_attributes_list, ",") - if ArrayHelper.isEmpty(azure_ad_attributes_list_array): - print("AzureAD: There is no attributes specified in azure_ad_attributes_list property") - return None - - gluu_ldap_attributes_list_array = StringHelper.split(gluu_ldap_attributes_list, ",") - if ArrayHelper.isEmpty(gluu_ldap_attributes_list_array): - print("AzureAD: There is no attributes specified in gluu_ldap_attributes_list property") - return None - - if len(azure_ad_attributes_list_array) != len(gluu_ldap_attributes_list_array): - print("AzureAD: The number of attributes isn't equal") - return None - - attributes_map = IdentityHashMap() - i = 0 - count = len(azure_ad_attributes_list_array) - while i < count: - azure_ad_attribute = StringHelper.toLowerCase(azure_ad_attributes_list_array[i]) - gluu_ldap_attribute = StringHelper.toLowerCase(gluu_ldap_attributes_list_array[i]) - attributes_map.put(azure_ad_attribute, gluu_ldap_attribute) - i = i + 1 - - return attributes_map - except Exception, err: - print("AzureAD: Exception inside prepareAttributesMapping " + str(err)) - - def prepareForStep(self, configuration_attributes, request_parameters, step): - if step == 1: - print "AzureAD. Prepare for Step 1" - return True - else: - return False - - def authenticate(self, configuration_attributes, request_parameters, step): - print "AzureAD. Inside authenticate. Step %d" % step - authentication_service = CdiUtil.bean(AuthenticationService) - identity = CdiUtil.bean(Identity) - - if step == 1: - print "AzureAD. Authenticate for step 1" - logged_in = self.authenticate_user_credentials(identity, authentication_service) - print "AzureAD. Status of User Credentials based Authentication : %r" % logged_in - if not logged_in: - return False - print "AzureAD. Authenticate successful for step %d" % step - return True - else: - return False - - def authenticate_user_credentials(self, identity, authentication_service): - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - print "AzureAD. user_name: %s" % user_name - logged_in = False - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - - # Special condition to allow for Gluu admin login - if StringHelper.equals(user_name, ADMIN): - return self.authenticate_user_in_gluu_ldap(authentication_service, user_name, user_password) - - # Authenticate user credentials with Azure AD non-interactively - azure_auth_response = self.authenticate_user_in_azure(azure_tenant_id, user_name, user_password, azure_client_id, azure_client_secret) - print "AzureAD. Value of azure_auth_response is %s" % azure_auth_response - azure_auth_response_json = json.loads(azure_auth_response) - if azure_user_uuid in azure_auth_response_json: - # Azure authentication has succeeded. User needs to be enrolled in Gluu LDAP - user = self.enroll_azure_user_in_gluu_ldap(azure_auth_response_json) - if user is None: - # User Enrollment in Gluu LDAP has failed - logged_in = False - else: - # Authenticating the user within Gluu - user_authenticated_in_gluu = authentication_service.authenticate(user.getUserId()) - print "AzureAD: Authentication status of the user enrolled in Gluu LDAP %r " % user_authenticated_in_gluu - return user_authenticated_in_gluu - else: - # Azure authentication has failed. - logged_in = False - return logged_in - - @staticmethod - def authenticate_user_in_azure(tenant_id, user_name, pwd, client_id, client_secret): - post_params_json = {'resource': AZURE_AD_GRAPH_RESOURCE_ENDPOINT, 'client_id': client_id, - 'client_secret': client_secret, 'username': user_name, 'password': pwd, - 'grant_type': 'password', 'scope': 'openid'} - post_params_url_encoded = urllib.urlencode(post_params_json) - headers_json = {'Content-type': 'application/x-www-form-urlencoded', - 'Accept': 'application/json'} - conn = httplib.HTTPSConnection(MICROSOFT_AUTHORITY_URL + ':443') - relative_url = '/' + tenant_id + '/oauth2/token' - conn.request('POST', relative_url, post_params_url_encoded, headers_json) - response = conn.getresponse() - # print response.status, response.reason - azure_response = response.read() - conn.close() - # print "Response Data: %s" % azure_response - azure_response_json = json.loads(azure_response) - if 'id_token' in azure_response_json: - id_token = azure_response_json['id_token'] - id_token_array = String(id_token).split("\\.") - id_token_payload = id_token_array[1] - id_token_payload_str = String(Base64.decodeBase64(id_token_payload), 'UTF-8') - return str(id_token_payload_str) - else: - return azure_response - - def enroll_azure_user_in_gluu_ldap(self, azure_auth_response_json): - user_service = CdiUtil.bean(UserService) - azure_user_uuid_value = azure_auth_response_json[azure_user_uuid] - found_user = self.find_user_from_gluu_ldap_by_attribute(user_service, gluu_ldap_uuid, azure_user_uuid_value) - print "AzureAD. Value of found_user is %s" % found_user - if found_user is None: - new_user = User() - self.populate_user_obj_with_azure_user_data(new_user, azure_auth_response_json) - try: - # Add azure user in Gluu LDAP - found_user = user_service.addUser(new_user, True) - found_user_id = found_user.getUserId() - print("AzureAD: Azure User added successfully in Gluu LDAP " + found_user_id) - except Exception, err: - print("AzureAD: Error in adding azure user to Gluu LDAP:" + str(err)) - return None - else: - self.populate_user_obj_with_azure_user_data(found_user, azure_auth_response_json) - try: - # Update the user in Gluu LDAP with latest values from Azure AD - found_user = user_service.updateUser(found_user) - found_user_id = found_user.getUserId() - print("AzureAD: Azure User updated successfully in Gluu LDAP " + found_user_id) - except Exception, err: - print("AzureAD: Error in updating azure user to Gluu LDAP:" + str(err)) - return None - - return found_user - - @staticmethod - def populate_user_obj_with_azure_user_data(user, azure_auth_response_json): - # attributes_mapping = ["oid:uid", "given_name:givenName", "family_name:sn", "upn:mail"] - for attributesMappingEntry in attributes_mapping.entrySet(): - azure_ad_attribute_key = attributesMappingEntry.getKey() - gluu_ldap_attribute_key = attributesMappingEntry.getValue() - gluu_ldap_attribute_value = "undefined" - if azure_ad_attribute_key in azure_auth_response_json: - gluu_ldap_attribute_value = azure_auth_response_json[azure_ad_attribute_key] - print gluu_ldap_attribute_key + ' : ' + gluu_ldap_attribute_value - if (gluu_ldap_attribute_key is not None) & (gluu_ldap_attribute_value != "undefined"): - user.setAttribute(gluu_ldap_attribute_key, gluu_ldap_attribute_value) - return None - - @staticmethod - def authenticate_user_in_gluu_ldap(authentication_service, user_name, user_password): - return authentication_service.authenticate(user_name, user_password) - - @staticmethod - def find_user_from_gluu_ldap_by_attribute(user_service, attribute_name, attribute_value): - return user_service.getUserByAttribute(attribute_name, attribute_value) - - def getExtraParametersForStep(self, configuration_attributes, step): - return None - - def getCountAuthenticationSteps(self, configuration_attributes): - return 1 - - def getPageForStep(self, configuration_attributes, step): - return "" - - def destroy(self, configuration_attributes): - print "AzureAD. Destroy" - return True - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def getApiVersion(self): - return 11 - - def isValidAuthenticationMethod(self, usage_type, configuration_attributes): - return True - - def getAlternativeAuthenticationMethod(self, usage_type, configuration_attributes): - return None - - def logout(self, configuration_attributes, request_parameters): - return True - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/azuread/README.md b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/azuread/README.md deleted file mode 100644 index 2d25bca9ba3..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/azuread/README.md +++ /dev/null @@ -1,13 +0,0 @@ - -This is a person authentication module for oxAuth that allows user to authenticate against Azure AD. - -Required Custom property (key/value) - -1) azure_tenant_id (Azure AD's Tenant ID) -2) azure_client_id -3) azure_client_secret -4) azure_ad_attributes_list = oid,given_name,family_name,upn -5) gluu_ldap_attributes_list = uid,givenName,sn,mail - -Note: -An administrator of the Azure AD portal (portal.azure.com) needs to create an application for Gluu Server in the azure portal (with necessary permissions) -and configure the client id and client secret in the Custom properties of this Jython script. diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.change_password/BasicPassowrdUpdateExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.change_password/BasicPassowrdUpdateExternalAuthenticator.py deleted file mode 100644 index 6640e307eef..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.change_password/BasicPassowrdUpdateExternalAuthenticator.py +++ /dev/null @@ -1,124 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, AuthenticationService -from io.jans.util import StringHelper, ArrayHelper -from io.jans.as.server.util import ServerUtil - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic (with password update). Initialization" - print "Basic (with password update). Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Basic (with password update). Destroy" - print "Basic (with password update). Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - userService = CdiUtil.bean(UserService) - authenticationService = CdiUtil.bean(AuthenticationService) - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - user_name = credentials.getUsername() - - if (step == 1): - print "Basic (with password update). Authenticate for step 1" - - user_password = credentials.getPassword() - - logged_in = False - if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): - logged_in = authenticationService.authenticate(user_name, user_password) - - if (not logged_in): - return False - - return True - elif (step == 2): - print "Basic (with password update). Authenticate for step 2" - user = authenticationService.getAuthenticatedUser() - if user == None: - print "Basic (with password update). Authenticate for step 2. Failed to determine user name" - return False - - user_name = user.getUserId() - find_user_by_uid = userService.getUser(user_name) - - update_button = requestParameters.get("loginForm:updateButton") - - if ArrayHelper.isEmpty(update_button): - return True - - new_password_array = requestParameters.get("new_password") - if ArrayHelper.isEmpty(new_password_array) or StringHelper.isEmpty(new_password_array[0]): - print "Basic (with password update). Authenticate for step 2. New password is empty" - return False - - new_password = new_password_array[0] - find_user_by_uid.setAttribute("userPassword", new_password) - print "Basic (with password update). Authenticate for step 2. Attempting to set new user '%s' password" % user_name - - userService.updateUser(find_user_by_uid) - print "Basic (with password update). Authenticate for step 2. Password updated successfully" - - return True - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "Basic (with password update). Prepare for Step 1" - return True - elif (step == 2): - print "Basic (with password update). Prepare for Step 2" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 2 - - def getPageForStep(self, configurationAttributes, step): - if (step == 2): - return "/auth/pwd/newpassword.xhtml" - - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.change_password/auth/pwd/new-password.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.change_password/auth/pwd/new-password.xhtml deleted file mode 100644 index 12e85a6f232..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.change_password/auth/pwd/new-password.xhtml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - oxAuth - New Password - - - - - - -
-
- - - - - -
-
- -
-
\ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.client_group/BasicClientGroupExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.client_group/BasicClientGroupExternalAuthenticator.py deleted file mode 100644 index 6a4eda34261..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.client_group/BasicClientGroupExternalAuthenticator.py +++ /dev/null @@ -1,177 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, AuthenticationService, AppInitializer -from io.jans.util import StringHelper -from java.util import Arrays, HashMap - -import java -import json - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic (client group). Initialization" - - self.allow_default_login = False - if configurationAttributes.containsKey("allow_default_login"): - self.allow_default_login = StringHelper.toBoolean(configurationAttributes.get("allow_default_login").getValue2(), False) - - if not configurationAttributes.containsKey("configuration_file"): - print "Basic (client group). The property configuration_file is empty" - return False - - configurationFilePath = configurationAttributes.get("configuration_file").getValue2() - self.client_configurations = self.loadClientConfigurations(configurationFilePath) - if self.client_configurations == None: - print "Basic (client group). File with client configuration should be not empty" - return False - - print "Basic (client group). Initialized successfully" - return True - - def destroy(self, clientConfiguration): - print "Basic (client group). Destroy" - - print "Basic (client group). Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - -def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - session_attributes = identity.getSessionId().getSessionAttributes() - - client_id = session_attributes.get("client_id") - print "Basic (client group). Get client_id: '%s' authorization request" % client_id - - user_groups = self.client_configurations.get(client_id) - if user_groups == None: - print "Basic (client group). There is no user groups configuration for client_id '%s'. allow_default_login: %s" % (client_id, self.allow_default_login) - if not self.allow_default_login: - return False - - result = self.authenticateImpl(credentials, authenticationService) - return result - - is_member_client_groups = self.isUserMemberOfGroups(credentials, user_groups) - if not is_member_client_groups: - print "Basic (client group). User '%s' hasn't permissions to log into client_id '%s' application. " % (credentials.getUsername(), client_id) - return False - - result = self.authenticateImpl(credentials, authenticationService) - return result - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if step == 1: - print "Basic (client group). Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def logout(self, configurationAttributes, requestParameters): - return True - - def authenticateImpl(self, credentials, authenticationService): - print "Basic (client group). Processing user name/password authentication" - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - logged_in = authenticationService.authenticate(user_name, user_password) - - if not logged_in: - return False - - return True - - def loadClientConfigurations(self, configurationFile): - clientConfiguration = None - - # Load configuration from file - f = open(configurationFile, 'r') - try: - configurationFileJson = json.loads(f.read()) - except: - print "Basic (client group). Load configuration from file. Failed to load authentication configuration from file:", configurationFile - return None - finally: - f.close() - - clientConfigurations = HashMap() - for client_key in configurationFileJson.keys(): - client_config = configurationFileJson[client_key] - - client_inum = client_config["client_inum"] - user_groups_array = client_config["user_group"] - user_groups = Arrays.asList(user_groups_array) - clientConfigurations.put(client_inum, user_groups) - - print "Basic (client group). Load configuration from file. Loaded '%s' configurations" % clientConfigurations.size() - print clientConfigurations - - return clientConfigurations - - def isUserMemberOfGroups(self, credentials, groups): - userService = CdiUtil.bean(UserService) - - user_name = credentials.getUsername() - if StringHelper.isEmptyString(user_name): - return False - - find_user_by_uid = userService.getUser(user_name) - - is_member = False - member_of_list = find_user_by_uid.getAttributeValues("memberOf") - if member_of_list == None: - return is_member - - print member_of_list - print groups - - for member_of in member_of_list: - for group in groups: - if StringHelper.equalsIgnoreCase(group, member_of) or member_of.endswith(group): - is_member = True - break - - return is_member - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.client_group/client_group.json b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.client_group/client_group.json deleted file mode 100644 index 4476826fc46..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.client_group/client_group.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "client_1":{ - "client_inum":"client_inum_1", - "user_group":[ - "group_dn_1", - "group_dn_2" - ] - }, - "client_2":{ - "client_inum":"client_inum_2", - "user_group":[ - "group_dn_1", - "group_dn_2" - ] - } -} diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.external_logout/BasicExternalAuthenticatorWithExternalLogout.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.external_logout/BasicExternalAuthenticatorWithExternalLogout.py deleted file mode 100644 index 94e101a71c9..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.external_logout/BasicExternalAuthenticatorWithExternalLogout.py +++ /dev/null @@ -1,91 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import AuthenticationService -from io.jans.util import StringHelper - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic (with external logout). Initialization" - print "Basic (with external logout). Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Basic (with external logout). Destroy" - print "Basic (with external logout). Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - if (step == 1): - print "Basic (with external logout). Authenticate for step 1" - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): - logged_in = authenticationService.authenticate(user_name, user_password) - - if (not logged_in): - return False - - return True - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "Basic (with external logout). Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Basic (with external logout). Get external logout URL call" - return "https://www.dummy.org/app/logout.htm" - - # In order to get this method call RP should end_session request to https:///oxauth/logout.htm enpoint - # instead of https:///oxauth/restv1/end_session endpoint - def logout(self, configurationAttributes, requestParameters): - print "Basic (with external logout). Logout call" - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_auth_conf/BasicMultiAuthConfExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_auth_conf/BasicMultiAuthConfExternalAuthenticator.py deleted file mode 100644 index 56c0b26fde8..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_auth_conf/BasicMultiAuthConfExternalAuthenticator.py +++ /dev/null @@ -1,293 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, AuthenticationService, AppInitializer -from io.jans.as.server.service import MetricService -from io.jans.as.server.service.common import EncryptionService -from io.jans.model.metric import MetricType -from io.jans.util import StringHelper -from io.jans.util import ArrayHelper -from io.jans.orm.service import PersistanceFactoryService -from io.jans.orm.ldap.impl import LdapEntryManagerFactory -from io.jans.model.ldap import GluuLdapConfiguration -from java.util import Arrays, Properties - -import java -import json - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic (multi auth conf). Initialization" - - if (not configurationAttributes.containsKey("auth_configuration_file")): - print "Basic (multi auth conf). The property auth_configuration_file is empty" - return False - - authConfigurationFile = configurationAttributes.get("auth_configuration_file").getValue2() - authConfiguration = self.loadAuthConfiguration(authConfigurationFile) - if (authConfiguration == None): - print "Basic (multi auth conf). File with authentication configuration should be not empty" - return False - - validationResult = self.validateAuthConfiguration(authConfiguration) - if (not validationResult): - return False - - ldapExtendedEntryManagers = self.createLdapExtendedEntryManagers(authConfiguration) - if (ldapExtendedEntryManagers == None): - return False - - self.ldapExtendedEntryManagers = ldapExtendedEntryManagers - - print "Basic (multi auth conf). Initialized successfully" - return True - - def destroy(self, authConfiguration): - print "Basic (multi auth conf). Destroy" - - result = True - for ldapExtendedEntryManager in self.ldapExtendedEntryManagers: - ldapConfiguration = ldapExtendedEntryManager["ldapConfiguration"] - ldapEntryManager = ldapExtendedEntryManager["ldapEntryManager"] - - destoryResult = ldapEntryManager.destroy() - result = result and destoryResult - print "Basic (multi auth conf). Destroyed: " + ldapConfiguration.getConfigId() + ". Result: " + str(destoryResult) - - print "Basic (multi auth conf). Destroyed successfully" - - return result - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - if (step == 1): - print "Basic (multi auth conf). Authenticate for step 1" - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - metricService = CdiUtil.bean(MetricService) - timerContext = metricService.getTimer(MetricType.USER_AUTHENTICATION_RATE).time() - try: - keyValue = credentials.getUsername() - userPassword = credentials.getPassword() - - if (StringHelper.isNotEmptyString(keyValue) and StringHelper.isNotEmptyString(userPassword)): - for ldapExtendedEntryManager in self.ldapExtendedEntryManagers: - ldapConfiguration = ldapExtendedEntryManager["ldapConfiguration"] - ldapEntryManager = ldapExtendedEntryManager["ldapEntryManager"] - loginAttributes = ldapExtendedEntryManager["loginAttributes"] - localLoginAttributes = ldapExtendedEntryManager["localLoginAttributes"] - - print "Basic (multi auth conf). Authenticate for step 1. Using configuration: " + ldapConfiguration.getConfigId() - - idx = 0 - count = len(loginAttributes) - while (idx < count): - primaryKey = loginAttributes[idx] - localPrimaryKey = localLoginAttributes[idx] - - loggedIn = authenticationService.authenticate(ldapConfiguration, ldapEntryManager, keyValue, userPassword, primaryKey, localPrimaryKey) - if (loggedIn): - metricService.incCounter(MetricType.USER_AUTHENTICATION_SUCCESS) - return True - idx += 1 - finally: - timerContext.stop() - - metricService.incCounter(MetricType.USER_AUTHENTICATION_FAILURES) - - return False - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "Basic (multi auth conf). Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - - def loadAuthConfiguration(self, authConfigurationFile): - authConfiguration = None - - # Load authentication configuration from file - f = open(authConfigurationFile, 'r') - try: - authConfiguration = json.loads(f.read()) - except: - print "Basic (multi auth conf). Load auth configuration. Failed to load authentication configuration from file:", authConfigurationFile - return None - finally: - f.close() - - return authConfiguration - - def validateAuthConfiguration(self, authConfiguration): - isValid = True - - if (not ("ldap_configuration" in authConfiguration)): - print "Basic (multi auth conf). Validate auth configuration. There is no ldap_configuration section in configuration" - return False - - idx = 1 - for ldapConfiguration in authConfiguration["ldap_configuration"]: - if (not self.containsAttributeString(ldapConfiguration, "configId")): - print "Basic (multi auth conf). Validate auth configuration. There is no 'configId' attribute in ldap_configuration section #" + str(idx) - return False - - configId = ldapConfiguration["configId"] - - if (not self.containsAttributeArray(ldapConfiguration, "servers")): - print "Basic (multi auth conf). Validate auth configuration. Property 'servers' in configuration '" + configId + "' is invalid" - return False - - if (self.containsAttributeString(ldapConfiguration, "bindDN")): - if (not self.containsAttributeString(ldapConfiguration, "bindPassword")): - print "Basic (multi auth conf). Validate auth configuration. Property 'bindPassword' in configuration '" + configId + "' is invalid" - return False - - if (not self.containsAttributeString(ldapConfiguration, "useSSL")): - print "Basic (multi auth conf). Validate auth configuration. Property 'useSSL' in configuration '" + configId + "' is invalid" - return False - - if (not self.containsAttributeString(ldapConfiguration, "maxConnections")): - print "Basic (multi auth conf). Validate auth configuration. Property 'maxConnections' in configuration '" + configId + "' is invalid" - return False - - if (not self.containsAttributeArray(ldapConfiguration, "baseDNs")): - print "Basic (multi auth conf). Validate auth configuration. Property 'baseDNs' in configuration '" + configId + "' is invalid" - return False - - if (not self.containsAttributeArray(ldapConfiguration, "loginAttributes")): - print "Basic (multi auth conf). Validate auth configuration. Property 'loginAttributes' in configuration '" + configId + "' is invalid" - return False - - if (not self.containsAttributeArray(ldapConfiguration, "localLoginAttributes")): - print "Basic (multi auth conf). Validate auth configuration. Property 'localLoginAttributes' in configuration '" + configId + "' is invalid" - return False - - if (len(ldapConfiguration["loginAttributes"]) != len(ldapConfiguration["localLoginAttributes"])): - print "Basic (multi auth conf). Validate auth configuration. The number of attributes in 'loginAttributes' and 'localLoginAttributes' isn't equal in configuration '" + configId + "'" - return False - - idx += 1 - - return True - - def createLdapExtendedEntryManagers(self, authConfiguration): - ldapExtendedConfigurations = self.createLdapExtendedConfigurations(authConfiguration) - - appInitializer = CdiUtil.bean(AppInitializer) - persistanceFactoryService = CdiUtil.bean(PersistanceFactoryService) - ldapEntryManagerFactory = persistanceFactoryService.getPersistenceEntryManagerFactory(LdapEntryManagerFactory) - persistenceType = ldapEntryManagerFactory.getPersistenceType() - - ldapExtendedEntryManagers = [] - for ldapExtendedConfiguration in ldapExtendedConfigurations: - connectionConfiguration = ldapExtendedConfiguration["connectionConfiguration"] - ldapConfiguration = ldapExtendedConfiguration["ldapConfiguration"] - - ldapProperties = Properties() - for key, value in connectionConfiguration.items(): - value_string = value - if isinstance(value_string, list): - value_string = ", ".join(value) - else: - value_string = str(value) - - ldapProperties.setProperty(persistenceType + "." + key, value_string) - - if StringHelper.isNotEmptyString(ldapConfiguration.getBindPassword()): - ldapProperties.setProperty(persistenceType + ".bindPassword", ldapConfiguration.getBindPassword()) - - ldapEntryManager = ldapEntryManagerFactory.createEntryManager(ldapProperties) - - ldapExtendedEntryManagers.append({ "ldapConfiguration" : ldapConfiguration, "ldapProperties" : ldapProperties, "loginAttributes" : ldapExtendedConfiguration["loginAttributes"], "localLoginAttributes" : ldapExtendedConfiguration["localLoginAttributes"], "ldapEntryManager" : ldapEntryManager }) - - return ldapExtendedEntryManagers - - def createLdapExtendedConfigurations(self, authConfiguration): - ldapExtendedConfigurations = [] - - for connectionConfiguration in authConfiguration["ldap_configuration"]: - configId = connectionConfiguration["configId"] - - servers = connectionConfiguration["servers"] - - bindDN = None - bindPassword = None - useAnonymousBind = True - if (self.containsAttributeString(connectionConfiguration, "bindDN")): - useAnonymousBind = False - bindDN = connectionConfiguration["bindDN"] - bindPassword = CdiUtil.bean(EncryptionService).decrypt(connectionConfiguration["bindPassword"]) - - useSSL = connectionConfiguration["useSSL"] - maxConnections = connectionConfiguration["maxConnections"] - baseDNs = connectionConfiguration["baseDNs"] - loginAttributes = connectionConfiguration["loginAttributes"] - localLoginAttributes = connectionConfiguration["localLoginAttributes"] - - ldapConfiguration = GluuLdapConfiguration() - ldapConfiguration.setConfigId(configId) - ldapConfiguration.setBindDN(bindDN) - ldapConfiguration.setBindPassword(bindPassword) - ldapConfiguration.setServers(Arrays.asList(servers)) - ldapConfiguration.setMaxConnections(maxConnections) - ldapConfiguration.setUseSSL(useSSL) - ldapConfiguration.setBaseDNs(Arrays.asList(baseDNs)) - ldapConfiguration.setPrimaryKey(loginAttributes[0]) - ldapConfiguration.setLocalPrimaryKey(localLoginAttributes[0]) - ldapConfiguration.setUseAnonymousBind(useAnonymousBind) - - ldapExtendedConfigurations.append({ "ldapConfiguration" : ldapConfiguration, "connectionConfiguration" : connectionConfiguration, "loginAttributes" : loginAttributes, "localLoginAttributes" : localLoginAttributes }) - - return ldapExtendedConfigurations - - def containsAttributeString(self, dictionary, attribute): - return ((attribute in dictionary) and StringHelper.isNotEmptyString(dictionary[attribute])) - - def containsAttributeArray(self, dictionary, attribute): - return ((attribute in dictionary) and (len(dictionary[attribute]) > 0)) diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_login/BasicMultiLoginExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_login/BasicMultiLoginExternalAuthenticator.py deleted file mode 100644 index 1deacebf655..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multi_login/BasicMultiLoginExternalAuthenticator.py +++ /dev/null @@ -1,122 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, AuthenticationService -from io.jans.util import StringHelper, ArrayHelper - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic (multi login). Initialization" - - login_attributes_list_object = configurationAttributes.get("login_attributes_list") - if (login_attributes_list_object == None): - print "Basic (multi login). Initialization. There is no property login_attributes_list" - return False - - login_attributes_list = login_attributes_list_object.getValue2() - if (StringHelper.isEmpty(login_attributes_list)): - print "Basic (multi login). Initialization. There is no attributes specified in login_attributes property" - return False - - login_attributes_list_array = StringHelper.split(login_attributes_list, ",") - if (ArrayHelper.isEmpty(login_attributes_list_array)): - print "Basic (multi login). Initialization. There is no attributes specified in login_attributes property" - return False - - if (configurationAttributes.containsKey("local_login_attributes_list")): - local_login_attributes_list = configurationAttributes.get("local_login_attributes_list").getValue2() - local_login_attributes_list_array = StringHelper.split(local_login_attributes_list, ",") - else: - print "Basic (multi login). Initialization. There is no property local_login_attributes_list. Assuming that login attributes are equal to local login attributes." - local_login_attributes_list_array = login_attributes_list_array - - if (len(login_attributes_list_array) != len(local_login_attributes_list_array)): - print "Basic (multi login). Initialization. The number of attributes in login_attributes_list and local_login_attributes_list isn't equal" - return False - - self.login_attributes_list_array = login_attributes_list_array - self.local_login_attributes_list_array = local_login_attributes_list_array - - print "Basic (multi login). Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Basic (multi login). Destroy" - print "Basic (multi login). Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - if (step == 1): - print "Basic (multi login). Authenticate for step 1" - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - key_value = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if (StringHelper.isNotEmptyString(key_value) and StringHelper.isNotEmptyString(user_password)): - i = 0 - count = len(self.login_attributes_list_array) - while (i < count): - primary_key = self.login_attributes_list_array[i] - local_primary_key = self.local_login_attributes_list_array[i] - logged_in = authenticationService.authenticate(key_value, user_password, primary_key, local_primary_key) - if (logged_in): - return True - i += 1 - - return False - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "Basic (multi login). Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multiple_test_email_addresses/BasicMultipleTestEmailAddressesExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multiple_test_email_addresses/BasicMultipleTestEmailAddressesExternalAuthenticator.py deleted file mode 100644 index 86561e7cc1a..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.multiple_test_email_addresses/BasicMultipleTestEmailAddressesExternalAuthenticator.py +++ /dev/null @@ -1,97 +0,0 @@ - - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import AuthenticationService -from io.jans.util import StringHelper - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic. Initialization" - print "Basic. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Basic. Destroy" - print "Basic. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - if (step == 1): - print "Basic. Authenticate for step 1" - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - user_name_array = StringHelper.split(credentials.getUsername(),"+") - - user_name = None - - if len(user_name_array) == 2: - - email_id_array = StringHelper.split(user_name_array[1],"@") - user_name = user_name_array[0] + "@"+ email_id_array[1] - else: - - user_name = user_name_array[0] - - print "Username for authentication is: %s " % user_name - user_password = credentials.getPassword() - - logged_in = False - if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): - - logged_in = authenticationService.authenticate(user_name, user_password,"mail","mail") - - if (not logged_in): - return False - - return True - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "Basic. Prepare for Step 1" - return True - else: - return False - - def getNextStep(self, step, context): - return -1 - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.one_session/BasicOneSessionExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.one_session/BasicOneSessionExternalAuthenticator.py deleted file mode 100644 index b2ca688fb42..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.one_session/BasicOneSessionExternalAuthenticator.py +++ /dev/null @@ -1,118 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import AuthenticationService -from io.jans.orm import PersistenceEntryManager -from org.gluu.oxauth.model.ldap import TokenEntity -from io.jans.util import StringHelper -from jakarta.faces.application import FacesMessage -from io.jans.jsf2.message import FacesMessages -from org.gluu.oxauth.model.config import StaticConfiguration - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic (one session). Initialization" - self.entryManager = CdiUtil.bean(PersistenceEntryManager) - self.staticConfiguration = CdiUtil.bean(StaticConfiguration) - - print "Basic (one session). Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Basic (one session). Destroy" - print "Basic (one session). Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - if step == 1: - print "Basic (one session). Authenticate for step 1" - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - logged_in = authenticationService.authenticate(user_name, user_password) - - if not logged_in: - return False - - logged_in = self.isFirstSession(user_name) - if not logged_in: - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.add(FacesMessage.SEVERITY_ERROR, "Please, end active session first!") - return False - - - return True - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if step == 1: - print "Basic (one session). Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - - def isFirstSession(self, user_name): - tokenEntity = TokenEntity() - tokenEntity.setDn(self.staticConfiguration.getBaseDn().getClients()) - tokenEntity.setUserId(user_name) - - tokenEntityList = self.entryManager.findEntries(tokenEntity, 1) - print "Basic (one session). isFirstSession. Get result: '%s'" % tokenEntityList - - if (tokenEntityList != None) and (tokenEntityList.size() > 0): - print "Basic (one session). isFirstSession: False" - return False - - print "Basic (one session). isFirstSession: True" - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.password_expiration/PasswordExpiration.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.password_expiration/PasswordExpiration.py deleted file mode 100644 index 9fe12b577e2..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.password_expiration/PasswordExpiration.py +++ /dev/null @@ -1,149 +0,0 @@ -import datetime - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, AuthenticationService -from io.jans.util import StringHelper, ArrayHelper -from com.unboundid.util import StaticUtils -from java.util import GregorianCalendar, TimeZone -from java.util import Arrays - - -# This script expect that user has attribute oxPasswordExpirationDate with valid expiration date -class PersonAuthentication(PersonAuthenticationType): - - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic (with password update). Initialization" - print "Basic (with password update). Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Basic (with password update). Destroy" - print "Basic (with password update). Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - userService = CdiUtil.bean(UserService) - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - if step == 1: - print "Basic (with password update). Authenticate for step 1" - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - logged_in = authenticationService.authenticate(user_name, user_password) - - if not logged_in: - return False - - find_user_by_uid = authenticationService.getAuthenticatedUser() - user_expDate = find_user_by_uid.getAttribute("oxPasswordExpirationDate", False) - - if user_expDate == None: - print "Basic (with password update). Authenticate for step 1. User has no oxPasswordExpirationDate date" - return False - - dt = StaticUtils.decodeGeneralizedTime(user_expDate) - - # Get Current Date - calendar = GregorianCalendar(TimeZone.getTimeZone("UTC")); - now = calendar.getTime() - if now.compareTo(dt) > 0: - # Add 90 Days to current date - calendar.setTime(now) - calendar.add(calendar.DATE, 1) - dt_plus_90 = calendar.getTime() - expDate = StaticUtils.encodeGeneralizedTime(dt_plus_90) - identity.setWorkingParameter("expDate", expDate) - - return True - elif step == 2: - print "Basic (with password update). Authenticate for step 2" - user = authenticationService.getAuthenticatedUser() - if user == None: - print "Basic (with password update). Authenticate for step 2. Failed to determine user name" - return False - - user_name = user.getUserId() - find_user_by_uid = userService.getUser(user_name) - newExpDate = identity.getWorkingParameter("expDate") - if find_user_by_uid == None: - print "Basic (with password update). Authenticate for step 2. Failed to find user" - return False - print "Basic (with password update). Authenticate for step 2" - update_button = requestParameters.get("loginForm:updateButton") - - if ArrayHelper.isEmpty(update_button): - return True - - find_user_by_uid.setAttribute("oxPasswordExpirationDate", newExpDate) - new_password_array = requestParameters.get("loginForm:password") - if ArrayHelper.isEmpty(new_password_array) or StringHelper.isEmpty(new_password_array[0]): - print "Basic (with password update). Authenticate for step 2. New password is empty" - return False - - new_password = new_password_array[0] - find_user_by_uid.setAttribute("userPassword", new_password) - print "Basic (with password update). Authenticate for step 2. Attempting to set new user '%s' password" % user_name - - userService.updateUser(find_user_by_uid) - print "Basic (with password update). Authenticate for step 2. Password updated successfully" - - return True - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if step == 1: - print "Basic (with password update). Prepare for Step 1" - return True - elif step == 2: - print "Basic (with password update). Prepare for Step 2" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return Arrays.asList("expDate") - - def getCountAuthenticationSteps(self, configurationAttributes): - identity = CdiUtil.bean(Identity) - if identity.isSetWorkingParameter("expDate"): - return 2 - else: - return 1 - - def getPageForStep(self, configurationAttributes, step): - if step == 2: - return "/auth/pwd/newpassword.xhtml" - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.password_expiration/README.md b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.password_expiration/README.md deleted file mode 100644 index bf878afba06..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.password_expiration/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Password Expiration -The script would ask the user to update password after 90 days. diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.reset_to_step/BasicResetToStepExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.reset_to_step/BasicResetToStepExternalAuthenticator.py deleted file mode 100644 index 8979f0536c7..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/basic.reset_to_step/BasicResetToStepExternalAuthenticator.py +++ /dev/null @@ -1,100 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, AuthenticationService -from io.jans.util import StringHelper - - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Basic (demo reset step). Initialization" - print "Basic (demo reset step). Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Basic (demo reset step). Destroy" - print "Basic (demo reset step). Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - if 1 <= step <= 3: - print "Basic (demo reset step). Authenticate for step '%s'" % step - - identity = CdiUtil.bean(Identity) - identity.setWorkingParameter("pass_authentication", False) - - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): - userService = CdiUtil.bean(UserService) - logged_in = authenticationService.authenticate(user_name, user_password) - - if (not logged_in): - return False - - identity.setWorkingParameter("pass_authentication", True) - return True - else: - return False - - def getNextStep(self, configurationAttributes, requestParameters, step): - print "Basic (demo reset step). Get next step for step '%s'" % step - identity = CdiUtil.bean(Identity) - - # If user not pass current step authenticaton redirect to current step - pass_authentication = identity.getWorkingParameter("pass_authentication") - if not pass_authentication: - resultStep = step - print "Basic (demo reset step). Get next step. Changing step to '%s'" % resultStep - return resultStep - - return -1 - - def prepareForStep(self, configurationAttributes, requestParameters, step): - print "Basic (demo reset step). Prepare for step '%s'" % step - if 1 <= step <= 3: - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 3 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/bcrypt_ssha_migration/pwd_migration.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/bcrypt_ssha_migration/pwd_migration.py deleted file mode 100644 index d2f98d896cb..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/bcrypt_ssha_migration/pwd_migration.py +++ /dev/null @@ -1,148 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan, Chris Blanton -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import AuthenticationService -from io.jans.util import StringHelper -from io.jans.as.server.service import UserService -from io.jans.util.security import BCrypt - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "BCrypt Auth. Initialization" - print "BCrypt Auth. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "BCrypt Auth. Destroy" - print "BCrypt Auth. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - - authenticationService = CdiUtil.bean(AuthenticationService) - - if (step == 1): - print "BCrypt Auth. Authenticate for step 1" - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - - if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): - userService = CdiUtil.bean(UserService) - user = userService.getUser(user_name) - hashed_stored_pass = user.getAttribute("userPassword") - - password_schema = '' - - # Determine password schema - # Example for BCrypt: {BCRYPT}$2b$08$71gBXNKJ/iUBXqLjEdEXFesoUYQm5vrpKefi8YhV7ITGfAd9VNFaG - for char in hashed_stored_pass: - if char == '{': - continue - if char == '}': - break - password_schema = password_schema + char - print("Password Schema is: " + password_schema) - - # OpenDJ's SSHA(512) - if 'SSHA' in password_schema: - # Returns True if authenticated on the backend - logged_in = authenticationService.authenticate(user_name, user_password) - - # Pattern match BCRYPT and rewrite to SSHA - elif 'BCRYPT' in password_schema: - # Pull salt from the stored hashed password - salt = hashed_stored_pass[8:] - salt = salt.split("$")[3].strip() - salt = salt[0:22] - salt = '$2a$08$' + salt - - # Create BCrypt hash of challenge cleartext password using the gathered salt - challenge = BCrypt.hashpw(user_password,salt) - - # Strip unnecessary revision($2a$) and rounds(08$) from both hashed passwords for comparison. - challenge = challenge.split("$")[3].strip() - stored = hashed_stored_pass.split("$")[3].strip() - - print("Challenge Salt+Hash: " + challenge) - print("Stored Salt+Hash: " + stored) - - # Compare the hashses and update hash if there is a match. - if challenge in stored: - - # Users hashed challenge password matches the stored hashed password in the backend - # Therefore we update the users password to the backend's password schema by passing it to OpenDJ - print("Updating hash..") - user.setAttribute("userPassword",user_password) - user = userService.updateUser(user) - print("Logging in..") - - # Returns True - logged_in = authenticationService.authenticate(user_name) - - # Catch unknown schema types and output to oxauth_script.log - # This script can be expanded to include other password schemas. - else: - print("Unrecognized algorithm: " + password_schema) - - # If there is no match, logged_in will still be False and authentication will fail. - if (not logged_in): - return False - logged_in = authenticationService.authenticate(user_name) - return logged_in - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "BCrypt Auth. Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/cas2/Cas2ExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/cas2/Cas2ExternalAuthenticator.py deleted file mode 100644 index ae18806f7fe..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/cas2/Cas2ExternalAuthenticator.py +++ /dev/null @@ -1,338 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -import sys -from java.util import Arrays -from java.util import HashMap -from jakarta.faces.context import FacesContext -from org.apache.http.params import CoreConnectionPNames -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 UserService, AuthenticationService, RequestParameterService -from io.jans.as.server.service.net import HttpService -from io.jans.service.cdi.util import CdiUtil -from io.jans.util import StringHelper, ArrayHelper -from io.jans.jsf2.service import FacesService - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "CAS2. Initialization" - - if not configurationAttributes.containsKey("cas_host"): - print "CAS2. Initialization. Parameter 'cas_host' is missing" - return False - - self.cas_host = configurationAttributes.get("cas_host").getValue2() - - self.cas_extra_opts = None - if configurationAttributes.containsKey("cas_extra_opts"): - self.cas_extra_opts = configurationAttributes.get("cas_extra_opts").getValue2() - - - self.cas_renew_opt = False - if configurationAttributes.containsKey("cas_renew_opt"): - self.cas_renew_opt = StringHelper.toBoolean(configurationAttributes.get("cas_renew_opt").getValue2(), False) - - self.cas_map_user = False - if configurationAttributes.containsKey("cas_map_user"): - self.cas_map_user = StringHelper.toBoolean(configurationAttributes.get("cas_map_user").getValue2(), False) - - self.cas_enable_server_validation = False - if (configurationAttributes.containsKey("cas_validation_uri") and - configurationAttributes.containsKey("cas_validation_pattern") and - configurationAttributes.containsKey("cas_validation_timeout")): - - print "CAS2. Initialization. Configuring checker client" - self.cas_enable_server_validation = True - - self.cas_validation_uri = configurationAttributes.get("cas_validation_uri").getValue2() - self.cas_validation_pattern = configurationAttributes.get("cas_validation_pattern").getValue2() - cas_validation_timeout = int(configurationAttributes.get("cas_validation_timeout").getValue2()) * 1000 - - httpService = CdiUtil.bean(HttpService) - - self.http_client = httpService.getHttpsClient() - self.http_client_params = self.http_client.getParams() - self.http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, cas_validation_timeout) - - self.cas_alt_auth_mode = None - if configurationAttributes.containsKey("cas_alt_auth_mode"): - self.cas_alt_auth_mode = configurationAttributes.get("cas_alt_auth_mode").getValue2() - - print "CAS2. Initialized successfully" - - return True - - def destroy(self, configurationAttributes): - print "CAS2. Destroy" - if self.cas_enable_server_validation: - print "CAS2. CDestory. Destorying checker client" - self.http_client = None - - print "CAS2. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - if not self.cas_enable_server_validation: - return True - - print "CAS2. isValidAuthenticationMethod" - - httpService = CdiUtil.bean(HttpService) - - try: - http_service_response = httpService.executeGet(self.http_client, self.cas_validation_uri) - except: - print "CAS2. isValidAuthenticationMethod. Exception: ", sys.exc_info()[1] - return False - - try: - http_response = http_service_response.getHttpResponse() - if http_response.getStatusLine().getStatusCode() != 200: - print "CAS2. isValidAuthenticationMethod. Get invalid response from CAS2 server: ", str(http_response.getStatusLine().getStatusCode()) - httpService.consume(http_response) - return False - - validation_response_bytes = httpService.getResponseContent(http_response) - validation_response_string = httpService.convertEntityToString(validation_response_bytes) - httpService.consume(http_response) - finally: - http_service_response.closeConnection() - - if (validation_response_string == None) or (validation_response_string.find(self.cas_validation_pattern) == -1): - print "CAS2. isValidAuthenticationMethod. Get invalid login page from CAS2 server:" - return False - - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return self.cas_alt_auth_mode - - def authenticate(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - userService = CdiUtil.bean(UserService) - requestParameterService = CdiUtil.bean(RequestParameterService) - authenticationService = CdiUtil.bean(AuthenticationService) - httpService = CdiUtil.bean(HttpService) - - if step == 1: - print "CAS2. Authenticate for step 1" - ticket_array = requestParameters.get("ticket") - if ArrayHelper.isEmpty(ticket_array): - print "CAS2. Authenticate for step 1. ticket is empty" - return False - - ticket = ticket_array[0] - print "CAS2. Authenticate for step 1. ticket: " + ticket - - if StringHelper.isEmptyString(ticket): - print "CAS2. Authenticate for step 1. ticket is invalid" - return False - - # Validate ticket - facesContext = CdiUtil.bean(FacesContext) - request = facesContext.getExternalContext().getRequest() - - parametersMap = HashMap() - parametersMap.put("service", httpService.constructServerUrl(request) + "/postlogin.htm") - if self.cas_renew_opt: - parametersMap.put("renew", "true") - parametersMap.put("ticket", ticket) - cas_service_request_uri = requestParameterService.parametersAsString(parametersMap) - cas_service_request_uri = self.cas_host + "/serviceValidate?" + cas_service_request_uri - if self.cas_extra_opts != None: - cas_service_request_uri = cas_service_request_uri + "&" + self.cas_extra_opts - - print "CAS2. Authenticate for step 1. cas_service_request_uri: " + cas_service_request_uri - - http_client = httpService.getHttpsClient() - http_service_response = httpService.executeGet(http_client, cas_service_request_uri) - try: - validation_content = httpService.convertEntityToString(httpService.getResponseContent(http_service_response.getHttpResponse())) - finally: - http_service_response.closeConnection() - - print "CAS2. Authenticate for step 1. validation_content: " + validation_content - if StringHelper.isEmpty(validation_content): - print "CAS2. Authenticate for step 1. Ticket validation response is invalid" - return False - - cas2_auth_failure = self.parse_tag(validation_content, "cas:authenticationFailure") - print "CAS2. Authenticate for step 1. cas2_auth_failure: ", cas2_auth_failure - - cas2_user_uid = self.parse_tag(validation_content, "cas:user") - print "CAS2. Authenticate for step 1. cas2_user_uid: ", cas2_user_uid - - if (cas2_auth_failure != None) or (cas2_user_uid == None): - print "CAS2. Authenticate for step 1. Ticket is invalid" - return False - - if self.cas_map_user: - print "CAS2. Authenticate for step 1. Attempting to find user by oxExternalUid: cas2:" + cas2_user_uid - - # Check if the is user with specified cas2_user_uid - find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "cas2:" + cas2_user_uid) - - if find_user_by_uid == None: - print "CAS2. Authenticate for step 1. Failed to find user" - print "CAS2. Authenticate for step 1. Setting count steps to 2" - identity.setWorkingParameter("cas2_count_login_steps", 2) - identity.setWorkingParameter("cas2_user_uid", cas2_user_uid) - return True - - found_user_name = find_user_by_uid.getUserId() - print "CAS2. Authenticate for step 1. found_user_name: " + found_user_name - - authenticationService.authenticate(found_user_name) - - print "CAS2. Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("cas2_count_login_steps", 1) - - return True - else: - print "CAS2. Authenticate for step 1. Attempting to find user by uid:" + cas2_user_uid - - # Check if there is user with specified cas2_user_uid - find_user_by_uid = userService.getUser(cas2_user_uid) - if find_user_by_uid == None: - print "CAS2. Authenticate for step 1. Failed to find user" - return False - - found_user_name = find_user_by_uid.getUserId() - print "CAS2. Authenticate for step 1. found_user_name: " + found_user_name - - authenticationService.authenticate(found_user_name) - - print "CAS2. Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("cas2_count_login_steps", 1) - - return True - elif step == 2: - print "CAS2. Authenticate for step 2" - - if identity.isSetWorkingParameter("cas2_user_uid"): - print "CAS2. Authenticate for step 2. cas2_user_uid is empty" - return False - - cas2_user_uid = identity.getWorkingParameter("cas2_user_uid") - passed_step1 = StringHelper.isNotEmptyString(cas2_user_uid) - if not passed_step1: - return False - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - logged_in = authenticationService.authenticate(user_name, user_password) - - if not logged_in: - return False - - # Check if there is user which has cas2_user_uid - # Avoid mapping CAS2 account to more than one IDP account - find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "cas2:" + cas2_user_uid) - - if find_user_by_uid == None: - # Add cas2_user_uid to user one id UIDs - find_user_by_uid = userService.addUserAttribute(user_name, "oxExternalUid", "cas2:" + cas2_user_uid) - if find_user_by_uid == None: - print "CAS2. Authenticate for step 2. Failed to update current user" - return False - - return True - else: - found_user_name = find_user_by_uid.getUserId() - print "CAS2. Authenticate for step 2. found_user_name: " + found_user_name - - if StringHelper.equals(user_name, found_user_name): - return True - - return False - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if step == 1: - print "CAS2. Prepare for step 1" - - requestParameterService = CdiUtil.bean(RequestParameterService) - httpService = CdiUtil.bean(HttpService) - - facesContext = CdiUtil.bean(FacesContext) - request = facesContext.getExternalContext().getRequest() - - parametersMap = HashMap() - parametersMap.put("service", httpService.constructServerUrl(request) + "/postlogin.htm") - if self.cas_renew_opt: - parametersMap.put("renew", "true") - cas_service_request_uri = requestParameterService.parametersAsString(parametersMap) - cas_service_request_uri = self.cas_host + "/login?" + cas_service_request_uri - if self.cas_extra_opts != None: - cas_service_request_uri = cas_service_request_uri + "&" + self.cas_extra_opts - - print "CAS2. Prepare for step 1. cas_service_request_uri: " + cas_service_request_uri - facesService = CdiUtil.bean(FacesService) - facesService.redirectToExternalURL(cas_service_request_uri) - - return True - elif step == 2: - print "CAS2. Prepare for step 2" - - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - if step == 2: - return Arrays.asList("cas2_count_login_steps", "cas2_user_uid") - - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - identity = CdiUtil.bean(Identity) - if identity.isSetWorkingParameter("cas2_count_login_steps"): - return int(identity.getWorkingParameter("cas2_count_login_steps")) - - return 2 - - def getPageForStep(self, configurationAttributes, step): - identity = CdiUtil.bean(Identity) - if step == 1: - return "/auth/cas2/cas2login.xhtml" - return "/auth/cas2/cas2postlogin.xhtml" - - def parse_tag(self, str, tag): - tag1_pos1 = str.find("<" + tag) - # No tag found, return empty string. - if tag1_pos1 == -1: return None - tag1_pos2 = str.find(">", tag1_pos1) - if tag1_pos2 == -1: return None - tag2_pos1 = str.find("= 200 and responseStatus < 300 ) diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/compromised_password/compromised_password.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/compromised_password/compromised_password.py deleted file mode 100644 index b35cd40a58a..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/compromised_password/compromised_password.py +++ /dev/null @@ -1,223 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, AuthenticationService -from io.jans.util import StringHelper -import javax.crypto.spec.SecretKeySpec as SecretKeySpec -import javax.crypto.spec.IvParameterSpec as IvParameterSpec -import javax.crypto.Cipher -from javax.crypto import * -from io.jans.util import ArrayHelper -from java.util import Arrays -import urllib, urllib2, json - -import java -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "compromised_password. Initialization" - if not configurationAttributes.containsKey("secret_question"): - print "compromised_password. Initialization. Property secret_question is mandatory" - return False - self.secretquestion = configurationAttributes.get("secret_question").getValue2() - - if not configurationAttributes.containsKey("credentials_file"): - print "credentials_file property not defined" - return False - self.credentialfile = configurationAttributes.get("credentials_file").getValue2() - - if not configurationAttributes.containsKey("secret_answer"): - print "compromised_password. Initialization. Property secret_answer is mandatory" - return False - self.secretanswer = configurationAttributes.get("secret_answer").getValue2() - print "compromised_password. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "compromised_password. Destroy" - print "compromised_password. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - userService = CdiUtil.bean(UserService) - authenticationService = CdiUtil.bean(AuthenticationService) - - if step == 1: - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - logged_in = False - if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): - userService = CdiUtil.bean(UserService) - logged_in = authenticationService.authenticate(user_name, user_password) - if (not logged_in): - return False - else: - find_user_by_uid = authenticationService.getAuthenticatedUser() - status_attribute_value = userService.getCustomAttribute(find_user_by_uid, "mail") - user_mail = status_attribute_value.getValue() - self.setRequestScopedParameters(identity) - isCompromised = False - isCompromised = self.is_compromised(user_mail,user_password,configurationAttributes) - if(isCompromised): - identity.setWorkingParameter("pwd_compromised", isCompromised) - identity.setWorkingParameter("user_name", user_name) - return True - else: - return True - elif step == 2: - print "compromised_password. Authenticate for step 2" - form_answer_array = requestParameters.get("loginForm:question") - if ArrayHelper.isEmpty(form_answer_array): - return False - form_answer = form_answer_array[0] - if (form_answer == self.secretanswer): - return True - return False - elif step == 3: - authenticationService = CdiUtil.bean(AuthenticationService) - print "compromised_password (with password update). Authenticate for step 3" - userService = CdiUtil.bean(UserService) - update_button = requestParameters.get("loginForm:updateButton") - new_password_array = requestParameters.get("new_password") - if ArrayHelper.isEmpty(new_password_array) or StringHelper.isEmpty(new_password_array[0]): - print "compromised_password (with password update). Authenticate for step 3. New password is empty" - return False - new_password = new_password_array[0] - - user = authenticationService.getAuthenticatedUser() - if user == None: - print "compromised_password (with password update). Authenticate for step 3. Failed to determine user name" - return False - - user_name = user.getUserId() - print "compromised_password (with password update). Authenticate for step 3. Attempting to set new user '" + user_name + "' password" - find_user_by_uid = userService.getUser(user_name) - if (find_user_by_uid == None): - print "compromised_password (with password update). Authenticate for step 3. Failed to find user" - return False - - find_user_by_uid.setAttribute("userPassword", new_password) - userService.updateUser(find_user_by_uid) - print "compromised_password (with password update). Authenticate for step 3. Password updated successfully" - logged_in = authenticationService.authenticate(user_name) - return True - - def prepareForStep(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - self.setRequestScopedParameters(identity) - session_attributes = identity.getSessionId().getSessionAttributes() - pwdcompromised = session_attributes.get("pwd_compromised") - if(pwdcompromised != None): - if step == 1: - print "compromised_password. Prepare for step 1" - return True - elif step == 2: - print "compromised_password. Prepare for step 2" - return True - return False - else: - print "compromised_password. Prepare for step 1" - return True - - def getExtraParametersForStep(self, configurationAttributes, step): - return Arrays.asList("pwd_compromised","user_name") - - def getCountAuthenticationSteps(self, configurationAttributes): - identity = CdiUtil.bean(Identity) - self.setRequestScopedParameters(identity) - self.setRequestScopedParameters(identity) - session_attributes = identity.getSessionId().getSessionAttributes() - pwdcompromised = session_attributes.get("pwd_compromised") - if(pwdcompromised != None): - return 3 - return 1 - - def getPageForStep(self, configurationAttributes, step): - identity = CdiUtil.bean(Identity) - session_attributes = identity.getSessionId().getSessionAttributes() - pwdcompromised = session_attributes.get("pwd_compromised") - if(pwdcompromised != None): - if step == 2: - return "/auth/compromised/complogin.xhtml" - elif step == 3: - return "/auth/compromised/newpassword.xhtml" - return "" - else: - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - - def setRequestScopedParameters(self, identity): - identity.setWorkingParameter("question_label", self.secretquestion) - - def is_compromised(self, userid, password,configurationAttributes): - print "Vericloud APIs Initialization" - - vericloud_gluu_creds_file = self.credentialfile - # Load credentials from file - f = open(vericloud_gluu_creds_file, 'r') - try: - creds = json.loads(f.read()) - except: - print "Vericloud API. Initialize notification services. Failed to load credentials from file:", vericloud_gluu_creds_file - return False - finally: - f.close() - - try: - url = str(creds["api_url"]) - api_key=str(creds["api_key"]) - api_secret= str(creds["api_secret"]) - except: - print "Vericloud API. Initialize notification services. Invalid credentials file '%s' format:" % super_gluu_creds_file - return False - - - reqdata = {"mode":"search_leaked_password_with_userid", "api_key": api_key, "api_secret": api_secret, "userid": userid} - reqdata = urllib.urlencode(reqdata) - resp = urllib2.urlopen(urllib2.Request(url, reqdata)).read() - resp = json.loads(resp) - if resp['result'] != 'succeeded': - return None - for pass_enc in resp['passwords_encrypted']: - plaintext = self.AESCipherdecrypt(api_secret, pass_enc) - if (len(password), password[0], password[-1]) == (len(plaintext), plaintext[0], plaintext[-1]) : - return True - return False - - def AESCipherdecrypt(self, key, enc ): - enc, iv = enc.split(':') - cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING") - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key.decode("hex"), "AES"),IvParameterSpec(iv.decode("hex"))) - decrypted_password = cipher.doFinal(enc.decode("hex")) - return decrypted_password.tostring() diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/Attributes.json b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/Attributes.json deleted file mode 100644 index 951db1ef88e..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/Attributes.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "en": { - "givenName": "First Name", - "sn": "Last Name", - "mail": "Email", - "familyName": "Middle Name" - }, -"passStrength":2, -"domains": [] -} diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/README.md b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/README.md deleted file mode 100644 index c873b353973..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/README.md +++ /dev/null @@ -1,11 +0,0 @@ -In order to exceute the custom registration workflow, - -1. Add the following custom property(key:value) in the script properties: - -attributes_json_file_path: /etc/Attributes.json - -and place Attributes.json file in the path specified in the custom property. - -2. Place the reg.xhtml file in /opt/gluu/jetty/oxauth/custom/pages/auth/ directory. - -3. Enable the script and set it as the default authentication method. diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/reg.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/reg.xhtml deleted file mode 100644 index 24f3ea2da55..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/reg.xhtml +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - - - - - - - - -
- - - -
- - - -
-
diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/register.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/register.py deleted file mode 100644 index 275b37217ed..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/custom_registration/register.py +++ /dev/null @@ -1,268 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Jose Gonzalez -# Author: Gasmyr Mougang - -from org.gluu.oxauth.model.common import User, WebKeyStorage -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, AuthenticationService -from io.jans.as.server.util import ServerUtil -from io.jans.util import StringHelper, ArrayHelper -from java.util import Arrays -from jakarta.faces.application import FacesMessage -from io.jans.jsf2.message import FacesMessages -from email.mime.multipart import MIMEMultipart -from email.mime.text import MIMEText -from io.jans.service import MailService - - -import org.codehaus.jettison.json.JSONArray as JSONArray - -import json, ast -import java -import random -import jarray -import smtplib - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - self.emailid = None - self.identity = CdiUtil.bean(Identity) - - def init(self, customScript, configurationAttributes): - - print "Register. Initialized successfully" - if not (configurationAttributes.containsKey("attributes_json_file_path")): - #print "Cert. Initialization. Property chain_cert_file_path is mandatory" - return False - self.attributes_json_file_path = configurationAttributes.get("attributes_json_file_path").getValue2() - - return True - - def destroy(self, configurationAttributes): - print "Register. Destroy" - print "Register. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - - userService = CdiUtil.bean(UserService) - identity = CdiUtil.bean(Identity) - authenticationService = CdiUtil.bean(AuthenticationService) - - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.setKeepMessages() - - session_attributes = self.identity.getSessionId().getSessionAttributes() - form_passcode = ServerUtil.getFirstValue(requestParameters, "passcode") - - - print "Register. form_response_passcode: %s" % str(form_passcode) - - if step == 1: - print "inside step 1" - ufnm = ServerUtil.getFirstValue(requestParameters, "fnm") - ulnm = ServerUtil.getFirstValue(requestParameters, "lnm") - umnm = ServerUtil.getFirstValue(requestParameters, "mnm") - umail = ServerUtil.getFirstValue(requestParameters, "email") - upass = ServerUtil.getFirstValue(requestParameters, "pass") - - - - #rufnm1 = identity.getWorkingParameter("vufnm") - #print "rufnm" - #print rufnm1 - - #print "Register. Step 1 Password Authentication" - - - - # Generate Random six digit code and store it in array - code = random.randint(100000, 999999) - - - # Get code and save it in LDAP temporarily with special session entry - self.identity.setWorkingParameter("vufnm", ufnm) - self.identity.setWorkingParameter("vulnm", ulnm) - self.identity.setWorkingParameter("vumnm", umnm) - self.identity.setWorkingParameter("vumail", umail) - self.identity.setWorkingParameter("vupass", upass) - self.identity.setWorkingParameter("code", code) - - try: - mailService = CdiUtil.bean(MailService) - subject = "Registration Details" - - - body = "

Welcome


" - - if ufnm is not None: - body = body + "

First Name : "+str(ufnm)+",

" - - else: - body = body - - - if ulnm is not None: - body = body + "

Last Name "+str(ulnm)+",

" - - else: - body = body - - - if umnm is not None: - body = body + "

Middle Name "+str(umnm)+",

" - - else: - body = body - - body = body + "

Email : "+str(umail)+",

Password : "+str(upass)+",

Use %s OTP to finish Registration.

" - - - mailService.sendMail(umail, None, subject, body, body) - - - return True - except Exception, ex: - facesMessages.add(FacesMessage.SEVERITY_ERROR,"Failed to send message to mobile phone") - print "Register. Error sending message to Twilio" - print "Register. Unexpected error:", ex - - return False - elif step == 2: - # Retrieve the session attribute - print "Register. Step 2 SMS/OTP Authentication" - code = session_attributes.get("code") - rufnm = identity.getWorkingParameter("vufnm") - rulnm = identity.getWorkingParameter("vulnm") - rumnm = identity.getWorkingParameter("vumnm") - rumail = identity.getWorkingParameter("vumail") - rupass = identity.getWorkingParameter("vupass") - - - - - - print "----------------------------------" - print "Register. Code: %s" % str(code) - print "----------------------------------" - - if code is None: - print "Register. Failed to find previously sent code" - return False - - if form_passcode is None: - print "Register. Passcode is empty" - return False - - if len(form_passcode) != 6: - print "Register. Passcode from response is not 6 digits: %s" % form_passcode - return False - - if form_passcode == code: - print "Register, SUCCESS! User entered the same code!" - - newUser = User() - newUser.setAttribute("givenName", rufnm) - newUser.setAttribute("sn", rulnm) - newUser.setAttribute("middleName", rumnm) - newUser.setAttribute("mail", rumail) - newUser.setAttribute("uid", rufnm) - newUser.setAttribute("userPassword", rupass) - userService.addUser(newUser, True) - - logged_in = False - logged_in = authenticationService.authenticate(rufnm, rupass) - - if (not logged_in): - return False - - return True - - #return True - - print "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - print "Register. FAIL! User entered the wrong code! %s != %s" % (form_passcode, code) - print "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - #facesMessages.add(facesMessage.SEVERITY_ERROR, "Incorrect Twilio code, please try again.") - - - - - - - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if step == 1: - print "Register. Prepare for Step 1" - identity = CdiUtil.bean(Identity) - print self.getAttributesFromJson() - print "pass strength" - print self.getPasswordStrength() - identity.setWorkingParameter("CustomAtrributes", self.getAttributesFromJson()) - identity.setWorkingParameter("passStrength", str(self.getPasswordStrength())) - return True - elif step == 2: - print "Register. Prepare for Step 2" - return True - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - if step == 1: - return Arrays.asList("CustomAtrributes","PasswordStrength") - elif step == 2: - return Arrays.asList("code","vufnm","vulnm","vumnm","vumail","vupass") - - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 2 - - def getPageForStep(self, configurationAttributes, step): - if step == 1: - return "/auth/reg.xhtml" - elif step == 2: - return "/auth/otp_sms/otp_sms.xhtml" - - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - - def getAttributesFromJson(self): - f = open(self.attributes_json_file_path) - data = json.load(f) - data = ast.literal_eval(json.dumps(data)) - attributes = data["en"].keys() - - jsonString = ",".join(attributes) - return jsonString - def getPasswordStrength(self): - f = open(self.attributes_json_file_path) - data = json.load(f) - data = ast.literal_eval(json.dumps(data)) - strength = data["passStrength"] - return strength diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/fortinet/FortinetExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/fortinet/FortinetExternalAuthenticator.py deleted file mode 100644 index 1660eca5aa9..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/fortinet/FortinetExternalAuthenticator.py +++ /dev/null @@ -1,127 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Madhumita Subramaniam -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import AuthenticationService -from io.jans.util import StringHelper - -from net.sourceforge.jradiusclient import RadiusClient -from net.sourceforge.jradiusclient import RadiusAttribute -from net.sourceforge.jradiusclient import RadiusAttributeValues -from net.sourceforge.jradiusclient import RadiusPacket - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Radius. Initialization" - if not configurationAttributes.containsKey("RADIUS_SERVER_IP"): - print "Fortinet. Initialization. Property RADIUS_SERVER_IP is mandatory" - return False - self.RADIUS_SERVER_IP = configurationAttributes.get("RADIUS_SERVER_IP").getValue2() - - if not configurationAttributes.containsKey("RADIUS_SERVER_SECRET"): - print "Fortinet. Initialization. Property RADIUS_SERVER_SECRET is mandatory" - return False - self.RADIUS_SERVER_SECRET = configurationAttributes.get("RADIUS_SERVER_SECRET").getValue2() - - if not configurationAttributes.containsKey("RADIUS_SERVER_AUTH_PORT"): - print "Fortinet. Initialization. Property RADIUS_SERVER_AUTH_PORT is mandatory" - return False - self.RADIUS_SERVER_AUTH_PORT = configurationAttributes.get("RADIUS_SERVER_AUTH_PORT").getValue2() - - if not configurationAttributes.containsKey("RADIUS_SERVER_ACCT_PORT"): - print "Fortinet. Initialization. Property RADIUS_SERVER_ACCT_PORT is mandatory" - return False - self.RADIUS_SERVER_ACCT_PORT = configurationAttributes.get("RADIUS_SERVER_ACCT_PORT").getValue2() - - print "Radius. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Radius. Destroy" - print "Radius. Destroyed successfully" - return True - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def getApiVersion(self): - return 11 - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - if (step == 1): - print "Radius. Authenticate for step 1" - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - if StringHelper.isNotEmptyString(user_name ) and StringHelper.isNotEmptyString(user_password ): - user_exists_in_gluu = authenticationService.authenticate(user_name ) - if user_exists_in_gluu : - client = RadiusClient(self.RADIUS_SERVER_IP,int (self.RADIUS_SERVER_AUTH_PORT), int(self.RADIUS_SERVER_ACCT_PORT), self.RADIUS_SERVER_SECRET) - accessRequest = RadiusPacket(RadiusPacket.ACCESS_REQUEST) - userNameAttribute = RadiusAttribute(RadiusAttributeValues.USER_NAME,user_name ) - userPasswordAttribute = RadiusAttribute(RadiusAttributeValues.USER_PASSWORD,user_password ) - accessRequest.setAttribute(userNameAttribute) - accessRequest.setAttribute(userPasswordAttribute) - accessResponse = client.authenticate(accessRequest) - print "Packet type - %s " % accessResponse.getPacketType() - if accessResponse.getPacketType() == RadiusPacket.ACCESS_ACCEPT: - return True - #elif accessResponse.getPacketType() == RadiusPacket.ACCESS_CHALLENGE: - # return False - - - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "Radius. Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - - - def printRadiusPacket(self, radiusPacket): - attributes = radiusPacket.getAttributes() - for attribute in attributes: - print("%s : %s" %attribute.getType() % attribute.getValue) \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/GooglePlusExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/GooglePlusExternalAuthenticator.py deleted file mode 100644 index 194cd39a498..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/GooglePlusExternalAuthenticator.py +++ /dev/null @@ -1,557 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -import java -import json -from java.util import Arrays, HashMap, IdentityHashMap -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from org.gluu.oxauth.client import TokenClient, TokenRequest, UserInfoClient -from org.gluu.oxauth.model.common import GrantType, AuthenticationMethod -from org.gluu.oxauth.model.common import User -from org.gluu.oxauth.model.jwt import Jwt, JwtClaimName -from io.jans.as.server.security import Identity -from io.jans.as.server.service import UserService, ClientService, AuthenticationService -from io.jans.service.cdi.util import CdiUtil -from io.jans.util import StringHelper, ArrayHelper - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Google+ Initialization" - - if (not configurationAttributes.containsKey("gplus_client_secrets_file")): - print "Google+ Initialization. The property gplus_client_secrets_file is empty" - return False - - clientSecretsFile = configurationAttributes.get("gplus_client_secrets_file").getValue2() - self.clientSecrets = self.loadClientSecrets(clientSecretsFile) - if (self.clientSecrets == None): - print "Google+ Initialization. File with Google+ client secrets should be not empty" - return False - - self.attributesMapping = None - if (configurationAttributes.containsKey("gplus_remote_attributes_list") and - configurationAttributes.containsKey("gplus_local_attributes_list")): - - remoteAttributesList = configurationAttributes.get("gplus_remote_attributes_list").getValue2() - if (StringHelper.isEmpty(remoteAttributesList)): - print "Google+ Initialization. The property gplus_remote_attributes_list is empty" - return False - - localAttributesList = configurationAttributes.get("gplus_local_attributes_list").getValue2() - if (StringHelper.isEmpty(localAttributesList)): - print "Google+ Initialization. The property gplus_local_attributes_list is empty" - return False - - self.attributesMapping = self.prepareAttributesMapping(remoteAttributesList, localAttributesList) - if (self.attributesMapping == None): - print "Google+ Initialization. The attributes mapping isn't valid" - return False - - self.extensionModule = None - if (configurationAttributes.containsKey("extension_module")): - extensionModuleName = configurationAttributes.get("extension_module").getValue2() - try: - self.extensionModule = __import__(extensionModuleName) - extensionModuleInitResult = self.extensionModule.init(configurationAttributes) - if (not extensionModuleInitResult): - return False - except ImportError, ex: - print "Google+ Initialization. Failed to load gplus_extension_module: '%s'" % extensionModuleName - print "Google+ Initialization. Unexpected error:", ex - return False - - print "Google+ Initialized successfully" - return True - - def destroy(self, authConfiguration): - print "Google+ Destroy" - print "Google+ Destroyed successfully" - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - userService = CdiUtil.bean(UserService) - authenticationService = CdiUtil.bean(AuthenticationService) - - mapUserDeployment = False - enrollUserDeployment = False - if (configurationAttributes.containsKey("gplus_deployment_type")): - deploymentType = StringHelper.toLowerCase(configurationAttributes.get("gplus_deployment_type").getValue2()) - - if (StringHelper.equalsIgnoreCase(deploymentType, "map")): - mapUserDeployment = True - if (StringHelper.equalsIgnoreCase(deploymentType, "enroll")): - enrollUserDeployment = True - - if (step == 1): - print "Google+ Authenticate for step 1" - - gplusAuthCodeArray = requestParameters.get("gplus_auth_code") - gplusAuthCode = gplusAuthCodeArray[0] - - # Check if user uses basic method to log in - useBasicAuth = False - if (StringHelper.isEmptyString(gplusAuthCode)): - useBasicAuth = True - - # Use basic method to log in - if (useBasicAuth): - print "Google+ Authenticate for step 1. Basic authentication" - - identity.setWorkingParameter("gplus_count_login_steps", 1) - - credentials = identity.getCredentials() - - userName = credentials.getUsername() - userPassword = credentials.getPassword() - - loggedIn = False - if (StringHelper.isNotEmptyString(userName) and StringHelper.isNotEmptyString(userPassword)): - userService = CdiUtil.bean(UserService) - loggedIn = authenticationService.authenticate(userName, userPassword) - - if (not loggedIn): - return False - - return True - - # Use Google+ method to log in - print "Google+ Authenticate for step 1. gplusAuthCode:", gplusAuthCode - - currentClientSecrets = self.getCurrentClientSecrets(self.clientSecrets, configurationAttributes, requestParameters) - if (currentClientSecrets == None): - print "Google+ Authenticate for step 1. Client secrets configuration is invalid" - return False - - print "Google+ Authenticate for step 1. Attempting to gets tokens" - tokenResponse = self.getTokensByCode(self.clientSecrets, configurationAttributes, gplusAuthCode) - if ((tokenResponse == None) or (tokenResponse.getIdToken() == None) or (tokenResponse.getAccessToken() == None)): - print "Google+ Authenticate for step 1. Failed to get tokens" - return False - else: - print "Google+ Authenticate for step 1. Successfully gets tokens" - - jwt = Jwt.parse(tokenResponse.getIdToken()) - # TODO: Validate ID Token Signature - - gplusUserUid = jwt.getClaims().getClaimAsString(JwtClaimName.SUBJECT_IDENTIFIER) - print "Google+ Authenticate for step 1. Found Google user ID in the ID token: '%s'" % gplusUserUid - - if (mapUserDeployment): - # Use mapping to local IDP user - print "Google+ Authenticate for step 1. Attempting to find user by oxExternalUid: 'gplus:%s'" % gplusUserUid - - # Check if there is user with specified gplusUserUid - foundUser = userService.getUserByAttribute("oxExternalUid", "gplus:" + gplusUserUid) - - if (foundUser == None): - print "Google+ Authenticate for step 1. Failed to find user" - print "Google+ Authenticate for step 1. Setting count steps to 2" - identity.setWorkingParameter("gplus_count_login_steps", 2) - identity.setWorkingParameter("gplus_user_uid", gplusUserUid) - return True - - foundUserName = foundUser.getUserId() - print "Google+ Authenticate for step 1. foundUserName: '%s'" % foundUserName - - userAuthenticated = authenticationService.authenticate(foundUserName) - if (userAuthenticated == False): - print "Google+ Authenticate for step 1. Failed to authenticate user" - return False - - print "Google+ Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("gplus_count_login_steps", 1) - - postLoginResult = self.extensionPostLogin(configurationAttributes, foundUser) - print "Google+ Authenticate for step 1. postLoginResult: '%s'" % postLoginResult - - return postLoginResult - elif (enrollUserDeployment): - # Use auto enrollment to local IDP - print "Google+ Authenticate for step 1. Attempting to find user by oxExternalUid: 'gplus:%s'" % gplusUserUid - - # Check if there is user with specified gplusUserUid - foundUser = userService.getUserByAttribute("oxExternalUid", "gplus:" + gplusUserUid) - - if (foundUser == None): - # Auto user enrollemnt - print "Google+ Authenticate for step 1. There is no user in LDAP. Adding user to local LDAP" - - print "Google+ Authenticate for step 1. Attempting to gets user info" - userInfoResponse = self.getUserInfo(currentClientSecrets, configurationAttributes, tokenResponse.getAccessToken()) - if ((userInfoResponse == None) or (userInfoResponse.getClaims().size() == 0)): - print "Google+ Authenticate for step 1. Failed to get user info" - return False - else: - print "Google+ Authenticate for step 1. Successfully gets user info" - - gplusResponseAttributes = userInfoResponse.getClaims() - - # Convert Google+ user claims to lover case - gplusResponseNormalizedAttributes = HashMap() - for gplusResponseAttributeEntry in gplusResponseAttributes.entrySet(): - gplusResponseNormalizedAttributes.put( - StringHelper.toLowerCase(gplusResponseAttributeEntry.getKey()), gplusResponseAttributeEntry.getValue()) - - currentAttributesMapping = self.getCurrentAttributesMapping(self.attributesMapping, configurationAttributes, requestParameters) - print "Google+ Authenticate for step 1. Using next attributes mapping '%s'" % currentAttributesMapping - - newUser = User() - for attributesMappingEntry in currentAttributesMapping.entrySet(): - remoteAttribute = attributesMappingEntry.getKey() - localAttribute = attributesMappingEntry.getValue() - - localAttributeValue = gplusResponseNormalizedAttributes.get(remoteAttribute) - if (localAttribute != None): - newUser.setAttribute(localAttribute, localAttributeValue) - - if (newUser.getAttribute("sn") == None): - newUser.setAttribute("sn", gplusUserUid) - - if (newUser.getAttribute("cn") == None): - newUser.setAttribute("cn", gplusUserUid) - - # Add mail to oxTrustEmail so that the user's - # email is available through the SCIM interface - # too. - if (newUser.getAttribute("oxTrustEmail") is None and - newUser.getAttribute("mail") is not None): - oxTrustEmail = { - "value": newUser.getAttribute("mail"), - "display": newUser.getAttribute("mail"), - "primary": True, - "operation": None, - "reference": None, - "type": "other" - } - newUser.setAttribute("oxTrustEmail", json.dumps(oxTrustEmail)) - - newUser.setAttribute("oxExternalUid", "gplus:" + gplusUserUid) - print "Google+ Authenticate for step 1. Attempting to add user '%s' with next attributes '%s'" % (gplusUserUid, newUser.getCustomAttributes()) - - foundUser = userService.addUser(newUser, True) - print "Google+ Authenticate for step 1. Added new user with UID: '%s'" % foundUser.getUserId() - - foundUserName = foundUser.getUserId() - print "Google+ Authenticate for step 1. foundUserName: '%s'" % foundUserName - - userAuthenticated = authenticationService.authenticate(foundUserName) - if (userAuthenticated == False): - print "Google+ Authenticate for step 1. Failed to authenticate user" - return False - - print "Google+ Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("gplus_count_login_steps", 1) - - print "Google+ Authenticate for step 1. Attempting to run extension postLogin" - postLoginResult = self.extensionPostLogin(configurationAttributes, foundUser) - print "Google+ Authenticate for step 1. postLoginResult: '%s'" % postLoginResult - - return postLoginResult - else: - # Check if there is user with specified gplusUserUid - print "Google+ Authenticate for step 1. Attempting to find user by uid: '%s'" % gplusUserUid - - foundUser = userService.getUser(gplusUserUid) - if (foundUser == None): - print "Google+ Authenticate for step 1. Failed to find user" - return False - - foundUserName = foundUser.getUserId() - print "Google+ Authenticate for step 1. foundUserName: '%s'" % foundUserName - - userAuthenticated = authenticationService.authenticate(foundUserName) - if (userAuthenticated == False): - print "Google+ Authenticate for step 1. Failed to authenticate user" - return False - - print "Google+ Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("gplus_count_login_steps", 1) - - postLoginResult = self.extensionPostLogin(configurationAttributes, foundUser) - print "Google+ Authenticate for step 1. postLoginResult: '%s'" % postLoginResult - - return postLoginResult - elif (step == 2): - print "Google+ Authenticate for step 2" - - sessionAttributes = identity.getSessionId().getSessionAttributes() - if (sessionAttributes == None) or not sessionAttributes.containsKey("gplus_user_uid"): - print "Google+ Authenticate for step 2. gplus_user_uid is empty" - return False - - gplusUserUid = sessionAttributes.get("gplus_user_uid") - passed_step1 = StringHelper.isNotEmptyString(gplusUserUid) - if (not passed_step1): - return False - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - userName = credentials.getUsername() - userPassword = credentials.getPassword() - - loggedIn = False - if (StringHelper.isNotEmptyString(userName) and StringHelper.isNotEmptyString(userPassword)): - loggedIn = authenticationService.authenticate(userName, userPassword) - - if (not loggedIn): - return False - - # Check if there is user which has gplusUserUid - # Avoid mapping Google account to more than one IDP account - foundUser = userService.getUserByAttribute("oxExternalUid", "gplus:" + gplusUserUid) - - if (foundUser == None): - # Add gplusUserUid to user one id UIDs - foundUser = userService.addUserAttribute(userName, "oxExternalUid", "gplus:" + gplusUserUid) - if (foundUser == None): - print "Google+ Authenticate for step 2. Failed to update current user" - return False - - postLoginResult = self.extensionPostLogin(configurationAttributes, foundUser) - print "Google+ Authenticate for step 2. postLoginResult: '%s'" % postLoginResult - - return postLoginResult - else: - foundUserName = foundUser.getUserId() - print "Google+ Authenticate for step 2. foundUserName: '%s'" % foundUserName - - if StringHelper.equals(userName, foundUserName): - postLoginResult = self.extensionPostLogin(configurationAttributes, foundUser) - print "Google+ Authenticate for step 2. postLoginResult: '%s'" % postLoginResult - - return postLoginResult - - return False - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - authenticationService = CdiUtil.bean(AuthenticationService) - - if (step == 1): - print "Google+ Prepare for step 1" - - currentClientSecrets = self.getCurrentClientSecrets(self.clientSecrets, configurationAttributes, requestParameters) - if (currentClientSecrets == None): - print "Google+ Prepare for step 1. Google+ client configuration is invalid" - return False - - identity.setWorkingParameter("gplus_client_id", currentClientSecrets["web"]["client_id"]) - identity.setWorkingParameter("gplus_client_secret", currentClientSecrets["web"]["client_secret"]) - - return True - elif (step == 2): - print "Google+ Prepare for step 2" - - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - if (step == 2): - return Arrays.asList("gplus_user_uid") - - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - identity = CdiUtil.bean(Identity) - if (identity.isSetWorkingParameter("gplus_count_login_steps")): - return identity.getWorkingParameter("gplus_count_login_steps") - - return 2 - - def getPageForStep(self, configurationAttributes, step): - if (step == 1): - return "/auth/gplus/gpluslogin.xhtml" - - return "/auth/gplus/gpluspostlogin.xhtml" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - # TODO Revoke token - return True - - def loadClientSecrets(self, clientSecretsFile): - clientSecrets = None - - # Load certificate from file - f = open(clientSecretsFile, 'r') - try: - clientSecrets = json.loads(f.read()) - except: - print "Failed to load Google+ client secrets from file: '%s'" % clientSecrets - return None - finally: - f.close() - - return clientSecrets - - def getClientConfiguration(self, configurationAttributes, requestParameters): - # Get client configuration - if (configurationAttributes.containsKey("gplus_client_configuration_attribute")): - clientConfigurationAttribute = configurationAttributes.get("gplus_client_configuration_attribute").getValue2() - print "Google+ GetClientConfiguration. Using client attribute: '%s'" % clientConfigurationAttribute - - if (requestParameters == None): - return None - - clientId = None - - # Attempt to determine client_id from request - clientIdArray = requestParameters.get("client_id") - if (ArrayHelper.isNotEmpty(clientIdArray) and StringHelper.isNotEmptyString(clientIdArray[0])): - clientId = clientIdArray[0] - - # Attempt to determine client_id from event context - if (clientId == None): - identity = CdiUtil.bean(Identity) - if (identity.isSetWorkingParameter("sessionAttributes")): - clientId = identity.getSessionId().getSessionAttributes().get("client_id") - - if (clientId == None): - print "Google+ GetClientConfiguration. client_id is empty" - return None - - clientService = CdiUtil.bean(ClientService) - client = clientService.getClient(clientId) - if (client == None): - print "Google+ GetClientConfiguration. Failed to find client '%s' in local LDAP" % clientId - return None - - clientConfiguration = clientService.getCustomAttribute(client, clientConfigurationAttribute) - if ((clientConfiguration == None) or StringHelper.isEmpty(clientConfiguration.getValue())): - print "Google+ GetClientConfiguration. Client '%s' attribute '%s' is empty" % (clientId, clientConfigurationAttribute) - else: - print "Google+ GetClientConfiguration. Client '%s' attribute '%s' is '%s'" % (clientId, clientConfigurationAttribute, clientConfiguration) - return clientConfiguration - - return None - - def getCurrentClientSecrets(self, currentClientSecrets, configurationAttributes, requestParameters): - clientConfiguration = self.getClientConfiguration(configurationAttributes, requestParameters) - if (clientConfiguration == None): - return currentClientSecrets - - clientConfigurationValue = json.loads(clientConfiguration.getValue()) - - return clientConfigurationValue["gplus"] - - def getCurrentAttributesMapping(self, currentAttributesMapping, configurationAttributes, requestParameters): - clientConfiguration = self.getClientConfiguration(configurationAttributes, requestParameters) - if (clientConfiguration == None): - return currentAttributesMapping - - clientConfigurationValue = json.loads(clientConfiguration.getValue()) - - clientAttributesMapping = self.prepareAttributesMapping(clientConfigurationValue["gplus_remote_attributes_list"], clientConfigurationValue["gplus_local_attributes_list"]) - if (clientAttributesMapping == None): - print "Google+ GetCurrentAttributesMapping. Client attributes mapping is invalid. Using default one" - return currentAttributesMapping - - return clientAttributesMapping - - def prepareAttributesMapping(self, remoteAttributesList, localAttributesList): - remoteAttributesListArray = StringHelper.split(remoteAttributesList, ",") - if (ArrayHelper.isEmpty(remoteAttributesListArray)): - print "Google+ PrepareAttributesMapping. There is no attributes specified in remoteAttributesList property" - return None - - localAttributesListArray = StringHelper.split(localAttributesList, ",") - if (ArrayHelper.isEmpty(localAttributesListArray)): - print "Google+ PrepareAttributesMapping. There is no attributes specified in localAttributesList property" - return None - - if (len(remoteAttributesListArray) != len(localAttributesListArray)): - print "Google+ PrepareAttributesMapping. The number of attributes in remoteAttributesList and localAttributesList isn't equal" - return None - - attributeMapping = IdentityHashMap() - containsUid = False - i = 0 - count = len(remoteAttributesListArray) - while (i < count): - remoteAttribute = StringHelper.toLowerCase(remoteAttributesListArray[i]) - localAttribute = StringHelper.toLowerCase(localAttributesListArray[i]) - attributeMapping.put(remoteAttribute, localAttribute) - - if (StringHelper.equalsIgnoreCase(localAttribute, "uid")): - containsUid = True - - i = i + 1 - - if (not containsUid): - print "Google+ PrepareAttributesMapping. There is no mapping to mandatory 'uid' attribute" - return None - - return attributeMapping - - def getTokensByCode(self, currentClientSecrets, configurationAttributes, code): - tokenRequest = TokenRequest(GrantType.CLIENT_CREDENTIALS) - tokenRequest.setAuthenticationMethod(AuthenticationMethod.CLIENT_SECRET_POST) - tokenRequest.setCode(code) - tokenRequest.setAuthUsername(currentClientSecrets["web"]["client_id"]) - tokenRequest.setAuthPassword(currentClientSecrets["web"]["client_secret"]) - tokenRequest.setRedirectUri("postmessage") - tokenRequest.setGrantType(GrantType.AUTHORIZATION_CODE) - - tokenClient = TokenClient(currentClientSecrets["web"]["token_uri"]) - tokenClient.setRequest(tokenRequest) - - tokenResponse = tokenClient.exec() - if ((tokenResponse == None) or (tokenResponse.getStatus() != 200)): - return None - - return tokenResponse - - def getUserInfo(self, currentClientSecrets, configurationAttributes, accessToken): - userInfoClient = UserInfoClient("https://www.googleapis.com/plus/v1/people/me/openIdConnect") - - userInfoResponse = userInfoClient.execUserInfo(accessToken) - if ((userInfoResponse == None) or (userInfoResponse.getStatus() != 200)): - return None - - return userInfoResponse - - def extensionPostLogin(self, configurationAttributes, user): - if (self.extensionModule != None): - try: - postLoginResult = self.extensionModule.postLogin(configurationAttributes, user) - print "Google+ PostLogin result: '%s'" % postLoginResult - - return postLoginResult - except Exception, ex: - print "Google+ PostLogin. Failed to execute postLogin method" - print "Google+ PostLogin. Unexpected error:", ex - return False - except java.lang.Throwable, ex: - print "Google+ PostLogin. Failed to execute postLogin method" - ex.printStackTrace() - return False - - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/sample/custom_script_entry.ldif b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/sample/custom_script_entry.ldif deleted file mode 100644 index e1f3815e76d..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/sample/custom_script_entry.ldif +++ /dev/null @@ -1,22 +0,0 @@ -dn: inum=@!1111!E521.2AE6,ou=scripts,o=gluu -objectClass: oxCustomScript -objectClass: top -displayName: gplus -gluuStatus: true -inum: @!1111!E521.2AE6 -oxConfigurationProperty: {"value1":"gplus_client_secrets_file","value2":"/et - c/certs/gplus_client_secrets.json","description":""} -oxConfigurationProperty: {"value1":"gplus_deployment_type","value2":"enroll" - ,"description":""} -oxConfigurationProperty: {"value1":"gplus_local_attributes_list","value2":"u - id, mail, givenName, sn, cn, preferredLanguage","description":""} -oxConfigurationProperty: {"value1":"gplus_remote_attributes_list","value2":" - email, email, given_name, family_name, given_name, locale","description":""} -oxLevel: 22 -oxModuleProperty: {"value1":"usage_type","value2":"interactive","description - ":""} -oxRevision: 1 -oxScript: -oxScriptType: person_authentication -programmingLanguage: python - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/sample/gplus_client_secrets.json b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/sample/gplus_client_secrets.json deleted file mode 100644 index 50c880ae891..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/sample/gplus_client_secrets.json +++ /dev/null @@ -1 +0,0 @@ -{"web":{"auth_uri":"https://accounts.google.com/o/oauth2/auth","client_secret":"","token_uri":"https://accounts.google.com/o/oauth2/token","client_email":"","redirect_uris":["https://myproductionurl.example.com/oauth2callback"],"client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/","client_id":"","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","javascript_origins":["https://myproductionurl.example.com"]}} \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/workflow.txt b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/workflow.txt deleted file mode 100644 index bf84de755f7..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/gplus/workflow.txt +++ /dev/null @@ -1,39 +0,0 @@ -title Google+ oxAuth external authenticator plugin - -User Agent -> oxTrust: Access site protected by mod_ox/shibboleth - -oxTrust -> oxAuth: Redirect for user authentication - -oxAuth -> User Agent: Show login form with Google+ widget - -User Agent -> Google Server: Log into Google account - -Google Server -> User Agent: Returns OAuth2 code, id_token, etc.. - -User Agent -> oxAuth: Send OAuth2 code to Google+ oxAuth external authenticator - -oxAuth -> Google Server: Get OAuth2 id_token by code - -Google Server -> oxAuth: Returns id_token - -oxAuth -> oxAuth: Get Subject Identifier (Google persistent Id) from id_token - -oxAuth -> oxAuth: Check if there is IDP user with oxExternalUid: "gplus:" + google_persistent_id (Google persistent Id) - -oxAuth -> oxTrust: Allow access if user with gplus:google_persistent_id exists - -oxTrust -> User Agent: Allow access to resource - -oxAuth -> oxAuth : Start enrollment if user with gplus:google_persistent_id not exists - -oxAuth -> Google Server: Get OAuth2 user profile - -Google Server -> oxAuth: Returns OAuth2 claims - -oxAuth -> oxAuth: Add new user with gplus:google_persistent_id. Map user claims to user attributes. Set status of new user to "register". - -oxAuth -> oxTrust: Allow access to resource - -oxTrust -> oxTrust: Show user registration form - -oxTrust -> User Agent: Allow access to resource diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/alter_login.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/alter_login.xhtml deleted file mode 100644 index ce3cede6062..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/alter_login.xhtml +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - - - - - - - - - - - - -
-
- - - - - -
-
- -
-
-
-
-
-

- - | - - - - - | - - - - - - | - - - - -

-
-
-
-
-
- - -
-
\ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/idfirst.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/idfirst.py deleted file mode 100644 index 526dfff723b..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/idfirst.py +++ /dev/null @@ -1,98 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Jose Gonzalez (based on acr_routerauthenticator.py) -# -# NOTE: before using this script, see the accompanying readme file - -from io.jans.as.server.security import Identity -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService -from io.jans.util import StringHelper -from io.jans.service.cdi.util import CdiUtil - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Identifier First. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Identifier First. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - print "Identifier First. isValidAuthenticationMethod called" - return False - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - print "Identifier First. getAlternativeAuthenticationMethod" - - identity = CdiUtil.bean(Identity) - user_name = identity.getCredentials().getUsername() - print "Identifier First. Inspecting user %s" % user_name - - attributes=identity.getSessionId().getSessionAttributes() - attributes.put("roUserName", user_name) - - acr = None - try: - userService = CdiUtil.bean(UserService) - foundUser = userService.getUserByAttribute("uid", user_name) - - if foundUser == None: - print "Identifier First. User does not exist" - return "" - - attr = configurationAttributes.get("acr_attribute").getValue2() - acr=foundUser.getAttribute(attr) - #acr="u2f" or "otp" or "twilio_sms", etc... - if acr == None: - acr = "basic" - except: - print "Identifier First. Error looking up user or his preferred method" - - print "Identifier First. new acr value %s" % acr - return acr - - def authenticate(self, configurationAttributes, requestParameters, step): - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - print "Identifier First. prepareForStep %s" % str(step) - return True - - def getExtraParametersForStep(self, configurationAttributes, step): - print "Identifier First. getExtraParametersForStep %s" % str(step) - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - print "Identifier First. getCountAuthenticationSteps called" - return 2 - - def getPageForStep(self, configurationAttributes, step): - print "Identifier First. getPageForStep called %s" % str(step) - if step == 1: - return "/auth/idfirst/idfirst_login.xhtml" - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - print "Identifier First. logout called" - return True diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/idfirst_login.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/idfirst_login.xhtml deleted file mode 100644 index 573ddb4dc2a..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/idfirst/idfirst_login.xhtml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - -
- - - - -
- -
-
\ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/UpdateToken.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/UpdateToken.py deleted file mode 100644 index 93d7be40ba0..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/UpdateToken.py +++ /dev/null @@ -1,72 +0,0 @@ -from __future__ import print_function - -from io.jans.service.cdi.util import CdiUtil -from io.jans.model.custom.script.type.token import UpdateTokenType -from io.jans.oxauth.service import SessionIdService -import sys - - -class UpdateToken(UpdateTokenType): - - def __init__(self, currentTimeMillis): - """Construct class. - - Args: - currentTimeMillis (int): current time in miliseconds - """ - self.currentTimeMillis = currentTimeMillis - - @classmethod - def init(cls, customScript, configurationAttributes): - print("Update token obconnect script. Initializing ...") - print("Update token obconnect script. Initialized successfully") - - return True - - @classmethod - def destroy(cls, configurationAttributes): - print("Update token obconnect script. Destroying ...") - print("Update token obconnect script. Destroyed successfully") - return True - - @classmethod - def getApiVersion(cls): - return 11 - - # Returns boolean, true - indicates that script applied changes - # This method is called after adding headers and claims. Hence script can override them - # Note : - # jsonWebResponse - is JwtHeader, you can use any method to manipulate JWT - # context is reference of io.jans.oxauth.service.external.context.ExternalUpdateTokenContext (in https://github.com/GluuFederation/oxauth project, ) - @classmethod - def modifyIdToken(cls, jsonWebResponse, context): - print("Update token obconnect script. Modify idToken: %s" % jsonWebResponse) - try : - sessionIdService = CdiUtil.bean(SessionIdService) - print("session id from context - %s" % context.getGrant().getSessionDn().strip("oxId=")) - - sessionId = sessionIdService.getSessionByDn(context.getGrant().getSessionDn()) # fetch from persistence - if sessionId is None: - print("Session Id is none") - else: - print("session id -%s " % sessionId.getId()) - - print("session id -%s " % sessionId.getSessionAttributes()) - openbanking_intent_id = sessionId.getSessionAttributes().get("openbanking_intent_id") - acr = sessionId.getSessionAttributes().get("acr_ob") - - #jsonWebResponse.getHeader().setClaim("custom_header_name", "custom_header_value") - - #custom claims - jsonWebResponse.getClaims().setClaim("openbanking_intent_id", openbanking_intent_id) - jsonWebResponse.getClaims().setClaim("acr", acr) - - #regular claims - jsonWebResponse.getClaims().setClaim("sub", openbanking_intent_id) - - print("Update token script. After modify idToken: %s" % jsonWebResponse) - - return True - except Exception as e: - print("update token failure" , e, sys.exc_info()[1]) - return None diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/obconnectExternalAuthentication.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/obconnectExternalAuthentication.py deleted file mode 100644 index 9ea868e5bec..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/obconnectExternalAuthentication.py +++ /dev/null @@ -1,246 +0,0 @@ -from __future__ import print_function - -from java.util import Arrays -from io.jans.service.cdi.util import CdiUtil -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.jsf2.service import FacesService -from io.jans.oxauth.util import ServerUtil -from io.jans.oxauth.service import UserService, SessionIdService -# please uncomment the following line when you need AuthenticationService -#from io.jans.oxauth.service import AuthenticationService -from io.jans.oxauth.model.common import User -from java.lang import String - -from com.nimbusds.jose import EncryptionMethod; -from com.nimbusds.jose import JWEAlgorithm; -from com.nimbusds.jose import JWEHeader; -from com.nimbusds.jose import JWEObject; -from com.nimbusds.jose import Payload; -from com.nimbusds.jose.crypto import DirectDecrypter; -from com.nimbusds.jose.crypto import DirectEncrypter; -import time -import sys - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - """Construct class. - - Args: - currentTimeMillis (int): current time in miliseconds - """ - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - - if (not configurationAttributes.containsKey("sharedSecret")): - print("Obconnect. Initialization. Property sharedSecret is not specified") - return False - else: - self.sharedSecret = configurationAttributes.get("sharedSecret").getValue2() - if (not configurationAttributes.containsKey("hostname")): - print("Obconnect. Initialization. Property hostname is not specified") - return False - else: - self.hostname = configurationAttributes.get("hostname").getValue2() - - if (not configurationAttributes.containsKey("tpp_client_id")): - print("Obconnect. Initialization. Property tpp_client_id is not specified") - return False - else: - self.tpp_client_id = configurationAttributes.get("tpp_client_id").getValue2() - - if (not configurationAttributes.containsKey("client_name")): - print("Obconnect. Initialization. Property client_name is not specified") - return False - else: - self.client_name = configurationAttributes.get("client_name").getValue2() - - if (not configurationAttributes.containsKey("organisation_name")): - print("Obconnect. Initialization. Property organisation_name is not specified") - return False - else: - self.organisation_name = configurationAttributes.get("organisation_name").getValue2() - - if (not configurationAttributes.containsKey("expiry")): - print("Obconnect. Initialization. Property expiry is not specified") - return False - else: - self.expiry = configurationAttributes.get("expiry").getValue2() - - if (not configurationAttributes.containsKey("consent_app_server_name")): - print("Obconnect. Initialization. Property consent_app_server_name is not specified") - return False - else: - self.consent_app_server_name = configurationAttributes.get("consent_app_server_name").getValue2() - - return True - - @classmethod - def destroy(cls, configurationAttributes): - return True - - @classmethod - def getApiVersion(cls): - return 11 - - @classmethod - def getAuthenticationMethodClaims(cls, requestParameters): - return None - - @classmethod - def isValidAuthenticationMethod(cls, usageType, configurationAttributes): - return True - - @classmethod - def getAlternativeAuthenticationMethod(cls, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - print("Obconnect. Authenticate. Step %s " % step) - - sessionData = ServerUtil.getFirstValue(requestParameters, "sessionData") - - jweObject = JWEObject.parse(sessionData) - #Decrypt - jweObject.decrypt(DirectDecrypter((String(self.sharedSecret)).getBytes())) - - # Get the plain text - payload = jweObject.getPayload() - print("session payload - "+payload.toString()) - # A successful authorization will always return the `result` claim with login and consent details - if payload.toJSONObject().get("result") is not None : - resultObject = payload.toJSONObject().get("result") - if resultObject.get("login") is not None and resultObject.get("consent") is not None: - print("Obconnect .successful Authentication") - # question: What is the purpose of the following line? - #authenticationService = CdiUtil.bean(AuthenticationService) - - # TODO: create a dummy user and authenticate - newUser = User() - uid = "obconnect_"+str(int(time.time()*1000.0)) - newUser.setAttribute("uid",uid) - - #TODO: add a new parameter called expiry and set expiry time - # TODO: A clean up task should be written which will delete this record - userService = CdiUtil.bean(UserService) - userService.addUser(newUser, True) - # TODO: create a dummy user and authenticate - #logged_in = authenticationService.authenticate(uid) - - openbanking_intent_id = resultObject.get("login").get("account") - acr_ob = resultObject.get("login").get("acr") - - # add a few things in session - sessionIdService = CdiUtil.bean(SessionIdService) - sessionId = sessionIdService.getSessionId() # fetch from persistence - sessionId.getSessionAttributes().put("openbanking_intent_id", openbanking_intent_id) - sessionId.getSessionAttributes().put("acr_ob", acr_ob ) - - return True - print ("Obconnect.Unsuccessful authentication") - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - print("Obconnect. prepare for step... %s" % step) - scope = ServerUtil.getFirstValue(requestParameters, "scope") - print("An example of accessing parameter from the request - Scope: %s " % scope) - #extract intent id from request object which is an encoded JWT - request = ServerUtil.getFirstValue(requestParameters, "request") - - jweObject = JWEObject.parse(request) - #Decrypt - jweObject.decrypt(DirectDecrypter((String(self.sharedSecret)).getBytes())) - - # Get the plain text - print("jweobject : %s " % jweObject) - payload = jweObject.getPayload() - print("Obconnect.Request payload containing intent id- %s- " % payload) - print(" open intent id %s - " % payload.toJSONObject().get("openbanking_intent_id")) - - # A successful authorization will always return the `result` claim with login and consent details - if payload.toJSONObject().get("openbanking_intent_id") is not None: - print("1.") - openbanking_intent_id = str(payload.toJSONObject().get("openbanking_intent_id")) - print("openbanking_intent_id %s" % openbanking_intent_id) - #sessionId = CdiUtil.bean(SessionIdService).getSessionId() - sessionId = "1231231231231" - print("sessionID : %s " % sessionId) - redirectURL = self.getRedirectURL (openbanking_intent_id, sessionId) - - print("Obconnect. Redirecting to ... %s " % redirectURL) - facesService = CdiUtil.bean(FacesService) - facesService.redirectToExternalURL(redirectURL) - return True - - print("Obconnect. Call to Gluu's /authorize endpoint should contain openbanking_intent_id as an encoded JWT") - return False - - @classmethod - def getCountAuthenticationSteps(cls, configurationAttributes): - return 1 - - @classmethod - def getNextStep(cls, configurationAttributes, requestParameters, step): - return -1 - - @classmethod - def getPageForStep(cls, configurationAttributes, step): - print("Obconnect. getPageForStep... %s" % step) - if step == 1: - return "/auth/redirect.xhtml" - - return "" - - @classmethod - def getExtraParametersForStep(cls, configurationAttributes, step): - return Arrays.asList("openbanking_intent_id", "acr_ob") - - @classmethod - def logout(cls, configurationAttributes, requestParameters): - return True - - @classmethod - def buildSessionIdObject(cls, hostname, intent_id_value,unique_identifier_for_session_object, - tpp_client_id, client_name,organisation_name, expiry) : - - sessionIdObject = "{\"returnTo\": \"" + hostname + "/oxauth/postlogin.htm" + \ - "\",\"prompt\": {\"name\": \"login\", \"details\" : { \"openbanking_intent_id\" : {" + \ - "\"value\": \"" + intent_id_value + "\", \"essential\" : \"true\"}}}, "+ " \"uid\" : \"" + \ - unique_identifier_for_session_object + "\" , \"params\" : { \"client_id\": \"" + \ - tpp_client_id+ "\", \"scope\": \"openid accounts\", \"claims\": " +\ - "\"{\\\"userinfo\\\":{\\\"openbanking_intent_id\\\":{\\\"value\\\":\\\"" + intent_id_value + \ - "\\\",\\\"essential\\\":true}},\\\"id_token\\\":{\\\"openbanking_intent_id\\\":{\\\"value\\\":\\\"" + \ - intent_id_value + "\\\",\\\"essential\\\":true},\\\"acr\\\":{\\\"values\\\":[\\\"urn:openbanking:psd2:sca\\\"\ - ,\\\"urn:openbanking:psd2:ca\\\"],\\\"essential\\\":true}}}\""+ "}, \"exp\" : " + expiry + \ - ", \"client\": { \"client_name\": \"" + client_name + "\",\"org_name\" : \""+ organisation_name + "\"}}" - - print("Obconnect. sessionIdObject: %s " % sessionIdObject) - return sessionIdObject - - def getRedirectURL (self, openbanking_intent_id, sessionID): - - #TODO: this is not required - unique_identifier_for_session_object = "12345" - - try : - # Create the header - header = JWEHeader(JWEAlgorithm.DIR, EncryptionMethod.A256GCM) - - # Create the payload - payloadString = self.buildSessionIdObject(self.hostname, openbanking_intent_id, unique_identifier_for_session_object, - self.tpp_client_id, self.client_name, self.organisation_name, self.expiry) - print("Payload String "+ payloadString) - payload = Payload(payloadString ) - - # Create the JWE object and encrypt it - jweObject = JWEObject(header, payload) - jweObject.encrypt( DirectEncrypter((String(self.sharedSecret)).getBytes())) - - # Serialise to compact JOSE form... - jweString = jweObject.serialize() - print("Redirect URL -->"+self.consent_app_server_name+"/?sessionData="+jweString) - return self.consent_app_server_name+"/?sessionData="+jweString - - except Exception as e: - print("Obconnect. Failed to build redirect URL -", e, sys.exc_info()[1]) - return None diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/redirect.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/redirect.xhtml deleted file mode 100644 index f39ade73837..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/obconnect/redirect.xhtml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/oneid/oneidlogin.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/oneid/oneidlogin.xhtml deleted file mode 100644 index 2b8cef3737f..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/oneid/oneidlogin.xhtml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - #{msgs['oneidlogin.title']} - - - - - - - - - \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/oneid/oneidpostlogin.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/oneid/oneidpostlogin.xhtml deleted file mode 100644 index 03b59826df0..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/oneid/oneidpostlogin.xhtml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - #{msgs['oneidlogin.title']} - - - - - - - - - - \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/Properties description.md b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/Properties description.md deleted file mode 100644 index 6e89b62ea40..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/Properties description.md +++ /dev/null @@ -1,25 +0,0 @@ -Script contents [here](https://github.com/JanssenProject/jans/jans-linux-setup/static/extension/person_authentication/OtpExternalAuthenticator.py) - -This is a person authentication script for jans-auth-server which enables one-time password for user authentication. - -The module has a few properties: - -1) otp_type - It's mandatory property. It's specify OTP mode: HOTP/ TOTP. - Allowed values: hotp/totp - Example: hotp - -2) issuer - It's mandatory property. It's company name. - Example: Janssen Inc - -3) otp_conf_file - It's mandatory property. It's specify path to OTP configuration JSON file. - Example: /etc/certs/otp_configuration.json - -4) label - It's label inside QR code. It's optional property. - Example: Janssen OTP - -5) qr_options - Specify width and height of QR image. It's optional property. - Example: qr_options: { width: 400, height: 400 } - -6) registration_uri - It's URL to page where user can register new account. It's optional property. - Example: https://ce-dev.jans.org/identity/register - \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/img/gluu_otp_integration_authentication_workflow.png b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/img/gluu_otp_integration_authentication_workflow.png deleted file mode 100644 index 4397d9d7b08..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/img/gluu_otp_integration_authentication_workflow.png and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/_remote.repositories b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/_remote.repositories deleted file mode 100644 index 095939909cc..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/_remote.repositories +++ /dev/null @@ -1,6 +0,0 @@ -#NOTE: This is an Aether internal implementation file, its format can be changed without prior notice. -#Mon Sep 26 13:13:34 MSK 2016 -oath-otp-keyprovisioning-0.0.1-SNAPSHOT.pom>= -oath-otp-keyprovisioning-0.0.1-SNAPSHOT-javadoc.jar>= -oath-otp-keyprovisioning-0.0.1-SNAPSHOT.jar>= -oath-otp-keyprovisioning-0.0.1-SNAPSHOT-sources.jar>= diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/maven-metadata-local.xml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/maven-metadata-local.xml deleted file mode 100644 index db499fc99c7..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/maven-metadata-local.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - com.lochbridge.oath - oath-otp-keyprovisioning - 0.0.1-SNAPSHOT - - - true - - 20160926101334 - - - javadoc - jar - 0.0.1-SNAPSHOT - 20160926101334 - - - sources - jar - 0.0.1-SNAPSHOT - 20160926101334 - - - jar - 0.0.1-SNAPSHOT - 20160926101334 - - - pom - 0.0.1-SNAPSHOT - 20160926101334 - - - - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT-javadoc.jar b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT-javadoc.jar deleted file mode 100644 index 65b92f445fe..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT-javadoc.jar and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT-sources.jar b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT-sources.jar deleted file mode 100644 index 3447afb492c..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT-sources.jar and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT.jar b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT.jar deleted file mode 100644 index 0b500623ba5..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT.jar and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT.pom b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT.pom deleted file mode 100644 index c6fd2787ad9..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/0.0.1-SNAPSHOT/oath-otp-keyprovisioning-0.0.1-SNAPSHOT.pom +++ /dev/null @@ -1,40 +0,0 @@ - - 4.0.0 - - com.lochbridge.oath - oath-parent - 0.0.1-SNAPSHOT - - oath-otp-keyprovisioning - OATH OTP Key Provisioning - A module for providing OTP key provisioning support. - - - 3.1.0 - - - - - com.google.guava - guava - - - - - com.google.zxing - core - ${com.google.zxing.version} - - - com.google.zxing - javase - ${com.google.zxing.version} - - - - com.lochbridge.oath - oath-otp - 0.0.1-SNAPSHOT - - - \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/maven-metadata-local.xml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/maven-metadata-local.xml deleted file mode 100644 index c7f4b52aff0..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp-keyprovisioning/maven-metadata-local.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - com.lochbridge.oath - oath-otp-keyprovisioning - - - 0.0.1-SNAPSHOT - - 20160926101334 - - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/_remote.repositories b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/_remote.repositories deleted file mode 100644 index 865f16cf7b5..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/_remote.repositories +++ /dev/null @@ -1,6 +0,0 @@ -#NOTE: This is an Aether internal implementation file, its format can be changed without prior notice. -#Mon Sep 26 13:13:32 MSK 2016 -oath-otp-0.0.1-SNAPSHOT.jar>= -oath-otp-0.0.1-SNAPSHOT-sources.jar>= -oath-otp-0.0.1-SNAPSHOT.pom>= -oath-otp-0.0.1-SNAPSHOT-javadoc.jar>= diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/maven-metadata-local.xml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/maven-metadata-local.xml deleted file mode 100644 index cfd6fa0c9cd..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/maven-metadata-local.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - com.lochbridge.oath - oath-otp - 0.0.1-SNAPSHOT - - - true - - 20160926101332 - - - javadoc - jar - 0.0.1-SNAPSHOT - 20160926101332 - - - sources - jar - 0.0.1-SNAPSHOT - 20160926101332 - - - jar - 0.0.1-SNAPSHOT - 20160926101332 - - - pom - 0.0.1-SNAPSHOT - 20160926101332 - - - - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT-javadoc.jar b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT-javadoc.jar deleted file mode 100644 index 9eca484ff18..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT-javadoc.jar and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT-sources.jar b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT-sources.jar deleted file mode 100644 index 03c2aabd55d..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT-sources.jar and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT.jar b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT.jar deleted file mode 100644 index 90dc6707916..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT.jar and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT.pom b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT.pom deleted file mode 100644 index 624ebdcc397..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/0.0.1-SNAPSHOT/oath-otp-0.0.1-SNAPSHOT.pom +++ /dev/null @@ -1,19 +0,0 @@ - - 4.0.0 - - com.lochbridge.oath - oath-parent - 0.0.1-SNAPSHOT - - oath-otp - OATH OTP - A module for generating and validating OTPs. - - - - com.google.guava - guava - - - \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/maven-metadata-local.xml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/maven-metadata-local.xml deleted file mode 100644 index e2477503be5..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-otp/maven-metadata-local.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - com.lochbridge.oath - oath-otp - - - 0.0.1-SNAPSHOT - - 20160926101332 - - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/_remote.repositories b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/_remote.repositories deleted file mode 100644 index d0af97df1ca..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/_remote.repositories +++ /dev/null @@ -1,3 +0,0 @@ -#NOTE: This is an Aether internal implementation file, its format can be changed without prior notice. -#Mon Sep 26 13:13:30 MSK 2016 -oath-parent-0.0.1-SNAPSHOT.pom>= diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/maven-metadata-local.xml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/maven-metadata-local.xml deleted file mode 100644 index 8ebf18a35f6..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/maven-metadata-local.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - com.lochbridge.oath - oath-parent - 0.0.1-SNAPSHOT - - - true - - 20160926101330 - - - pom - 0.0.1-SNAPSHOT - 20160926101330 - - - - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/oath-parent-0.0.1-SNAPSHOT.pom b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/oath-parent-0.0.1-SNAPSHOT.pom deleted file mode 100644 index ee4048d1aca..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/0.0.1-SNAPSHOT/oath-parent-0.0.1-SNAPSHOT.pom +++ /dev/null @@ -1,182 +0,0 @@ - - 4.0.0 - com.lochbridge.oath - oath-parent - 0.0.1-SNAPSHOT - pom - OATH Project - https://github.com/johnnymongiat/oath - - OATH provides components for building one-time password authentication systems. - - - - UTF-8 - UTF-8 - 18.0 - - - - - Johnny Mongiat - johnnymongiat@gmail.com - America/Montreal - - committer - - - - - - scm:git:https://github.com/johnnymongiat/oath.git - scm:git:https://github.com/johnnymongiat/oath.git - https://github.com/johnnymongiat/oath.git - - - - github - https://github.com/johnnymongiat/oath/issues - - - - Travis CI - https://travis-ci.org/johnnymongiat/oath - - - - - The MIT License (MIT) - http://opensource.org/licenses/MIT - manual - - - - - - junit - junit - 4.11 - test - - - org.mockito - mockito-core - 1.9.5 - test - - - - - - - com.google.guava - guava - ${guava.version} - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-source-plugin - 2.3 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - ${javadoc.doclint.none} - - - - attach-javadocs - - jar - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.5 - - - - true - - - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.6 - - - xml - html - - true - - - - org.eluder.coveralls - coveralls-maven-plugin - 3.0.1 - - - - - - - - org.apache.maven.plugins - maven-project-info-reports-plugin - 2.7 - - true - true - - - - - - - oath-otp - oath-otp-keyprovisioning - - - \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/maven-metadata-local.xml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/maven-metadata-local.xml deleted file mode 100644 index e496352c0f1..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/repository/com/lochbridge/oath/oath-parent/maven-metadata-local.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - com.lochbridge.oath - oath-parent - - - 0.0.1-SNAPSHOT - - 20160926101330 - - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/sample/otp_configuration.json b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/sample/otp_configuration.json deleted file mode 100644 index 43b27d1c9f7..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/sample/otp_configuration.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "htop":{ - "keyLength":20, - "digits":6, - "lookAheadWindow":1 - }, - "totp":{ - "keyLength":20, - "digits":6, - "timeStep":30, - "hmacShaAlgorithm": "sha1" - } -} diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/sequence_diagram.txt b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/sequence_diagram.txt deleted file mode 100644 index f03514bb36e..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/otp/sequence_diagram.txt +++ /dev/null @@ -1,31 +0,0 @@ -Title OTP enrollment/authentication workflow - -Person->Browser: Open RP URL -Browser->RP: Protected resource -RP->Gluu Server: Start AuthZ & AuthN -OTP Script->OTP Script: Verify user/password - -alt: User enrollment - OTP Script->OTP Script: Check if person not issued OTP key already - OTP Script->Browser: Render otpauth QR code with OTP key - Person->OTP comp. auth.: Scan QR code - OTP comp. auth.->Person: New one time password - Person->Browser: Enter one time password - Browser->OTP Script: - OTP Script->OTP Script: Validate one time password - OTP Script->OTP Script: Strore OTP key in user entry - OTP Script->Gluu Server: User pass enrollment -else User authentication - OTP Script->OTP Script: Check if person issued OTP key already - OTP comp. auth.->Person: New one time password - Person->Browser: Enter one time password - Browser->OTP Script: - OTP Script->OTP Script: Validate one time password - OTP Script->Gluu Server: User pass enrollment -end - -Gluu Server->Browser: Return code -Browser->RP: Return code - -RP->Gluu Server: Request tokens -RP->Gluu Server: Request user_info diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/PassportExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/PassportExternalAuthenticator.py deleted file mode 100644 index 01bc629af60..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/PassportExternalAuthenticator.py +++ /dev/null @@ -1,631 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Jose Gonzalez -# Author: Yuriy Movchan -# -from io.jans.jsf2.service import FacesService -from io.jans.jsf2.message import FacesMessages - -from org.gluu.oxauth.model.common import User, WebKeyStorage -from org.gluu.oxauth.model.configuration import AppConfiguration -from org.gluu.oxauth.model.crypto import CryptoProviderFactory -from org.gluu.oxauth.model.jwt import Jwt, JwtClaimName -from org.gluu.oxauth.model.util import Base64Util -from io.jans.as.server.service import AppInitializer, AuthenticationService -from io.jans.as.server.service.common import UserService, EncryptionService -from io.jans.as.server.service.net import HttpService -from io.jans.as.server.security import Identity -from io.jans.as.server.util import ServerUtil -from org.gluu.config.oxtrust import LdapOxPassportConfiguration -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.orm import PersistenceEntryManager -from io.jans.service.cdi.util import CdiUtil -from io.jans.util import StringHelper -from java.util import ArrayList, Arrays, Collections - -from jakarta.faces.application import FacesMessage -from jakarta.faces.context import FacesContext - -import json -import sys -import datetime - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Passport. init called" - - self.extensionModule = self.loadExternalModule(configurationAttributes.get("extension_module")) - extensionResult = self.extensionInit(configurationAttributes) - if extensionResult != None: - return extensionResult - - print "Passport. init. Behaviour is social" - success = self.processKeyStoreProperties(configurationAttributes) - - if success: - self.providerKey = "provider" - self.customAuthzParameter = self.getCustomAuthzParameter(configurationAttributes.get("authz_req_param_provider")) - self.passportDN = self.getPassportConfigDN() - print "Passport. init. Initialization success" - else: - print "Passport. init. Initialization failed" - return success - - - def destroy(self, configurationAttributes): - print "Passport. destroy called" - return True - - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - - def authenticate(self, configurationAttributes, requestParameters, step): - - extensionResult = self.extensionAuthenticate(configurationAttributes, requestParameters, step) - if extensionResult != None: - return extensionResult - - print "Passport. authenticate for step %s called" % str(step) - identity = CdiUtil.bean(Identity) - - # Loading self.registeredProviders in case passport destroyed - if not hasattr(self,'registeredProviders'): - print "Passport. Fetching registered providers." - self.parseProviderConfigs() - - if step == 1: - # Get JWT token - jwt_param = ServerUtil.getFirstValue(requestParameters, "user") - - if jwt_param != None: - print "Passport. authenticate for step 1. JWT user profile token found" - - # Parse JWT and validate - jwt = Jwt.parse(jwt_param) - if not self.validSignature(jwt): - return False - - if self.jwtHasExpired(jwt): - return False - - (user_profile, jsonp) = self.getUserProfile(jwt) - if user_profile == None: - return False - - sessionAttributes = identity.getSessionId().getSessionAttributes() - self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get("skipPassportProfileUpdate"), "true") - - return self.attemptAuthentication(identity, user_profile, jsonp) - - #See passportlogin.xhtml - provider = ServerUtil.getFirstValue(requestParameters, "loginForm:provider") - if StringHelper.isEmpty(provider): - - #it's username + passw auth - print "Passport. authenticate for step 1. Basic authentication detected" - logged_in = False - - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - authenticationService = CdiUtil.bean(AuthenticationService) - logged_in = authenticationService.authenticate(user_name, user_password) - - print "Passport. authenticate for step 1. Basic authentication returned: %s" % logged_in - return logged_in - - elif provider in self.registeredProviders: - #it's a recognized external IDP - identity.setWorkingParameter("selectedProvider", provider) - print "Passport. authenticate for step 1. Retrying step 1" - #see prepareForStep (step = 1) - return True - - if step == 2: - mail = ServerUtil.getFirstValue(requestParameters, "loginForm:email") - jsonp = identity.getWorkingParameter("passport_user_profile") - - if mail == None: - self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email was missing in user profile") - elif jsonp != None: - # Completion of profile takes place - user_profile = json.loads(jsonp) - user_profile["mail"] = [ mail ] - - return self.attemptAuthentication(identity, user_profile, jsonp) - - print "Passport. authenticate for step 2. Failed: expected mail value in HTTP request and json profile in session" - return False - - - def prepareForStep(self, configurationAttributes, requestParameters, step): - - extensionResult = self.extensionPrepareForStep(configurationAttributes, requestParameters, step) - if extensionResult != None: - return extensionResult - - print "Passport. prepareForStep called %s" % str(step) - identity = CdiUtil.bean(Identity) - - if step == 1: - #re-read the strategies config (for instance to know which strategies have enabled the email account linking) - self.parseProviderConfigs() - identity.setWorkingParameter("externalProviders", json.dumps(self.registeredProviders)) - - providerParam = self.customAuthzParameter - url = None - - sessionAttributes = identity.getSessionId().getSessionAttributes() - self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get("skipPassportProfileUpdate"), "true") - - #this param could have been set previously in authenticate step if current step is being retried - provider = identity.getWorkingParameter("selectedProvider") - if provider != None: - url = self.getPassportRedirectUrl(provider) - identity.setWorkingParameter("selectedProvider", None) - - elif providerParam != None: - paramValue = sessionAttributes.get(providerParam) - - if paramValue != None: - print "Passport. prepareForStep. Found value in custom param of authorization request: %s" % paramValue - provider = self.getProviderFromJson(paramValue) - - if provider == None: - print "Passport. prepareForStep. A provider value could not be extracted from custom authorization request parameter" - elif not provider in self.registeredProviders: - print "Passport. prepareForStep. Provider '%s' not part of known configured IDPs/OPs" % provider - else: - url = self.getPassportRedirectUrl(provider) - - if url == None: - print "Passport. prepareForStep. A page to manually select an identity provider will be shown" - else: - facesService = CdiUtil.bean(FacesService) - facesService.redirectToExternalURL(url) - - return True - - - def getExtraParametersForStep(self, configurationAttributes, step): - print "Passport. getExtraParametersForStep called" - if step == 1: - return Arrays.asList("selectedProvider", "externalProviders") - elif step == 2: - return Arrays.asList("passport_user_profile") - return None - - - def getCountAuthenticationSteps(self, configurationAttributes): - print "Passport. getCountAuthenticationSteps called" - identity = CdiUtil.bean(Identity) - if identity.getWorkingParameter("passport_user_profile") != None: - return 2 - return 1 - - - def getPageForStep(self, configurationAttributes, step): - print "Passport. getPageForStep called" - - extensionResult = self.extensionGetPageForStep(configurationAttributes, step) - if extensionResult != None: - return extensionResult - - if step == 1: - return "/auth/passport/passportlogin.xhtml" - return "/auth/passport/passportpostlogin.xhtml" - - - def getNextStep(self, configurationAttributes, requestParameters, step): - - if step == 1: - identity = CdiUtil.bean(Identity) - provider = identity.getWorkingParameter("selectedProvider") - if provider != None: - return 1 - - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - -# Extension module related functions - - def extensionInit(self, configurationAttributes): - - if self.extensionModule == None: - return None - return self.extensionModule.init(configurationAttributes) - - - def extensionAuthenticate(self, configurationAttributes, requestParameters, step): - - if self.extensionModule == None: - return None - return self.extensionModule.authenticate(configurationAttributes, requestParameters, step) - - - def extensionPrepareForStep(self, configurationAttributes, requestParameters, step): - - if self.extensionModule == None: - return None - return self.extensionModule.prepareForStep(configurationAttributes, requestParameters, step) - - - def extensionGetPageForStep(self, configurationAttributes, step): - - if self.extensionModule == None: - return None - return self.extensionModule.getPageForStep(configurationAttributes, step) - -# Initalization routines - - def loadExternalModule(self, simpleCustProperty): - - if simpleCustProperty != None: - print "Passport. loadExternalModule. Loading passport extension module..." - moduleName = simpleCustProperty.getValue2() - try: - module = __import__(moduleName) - return module - except: - print "Passport. loadExternalModule. Failed to load module %s" % moduleName - print "Exception: ", sys.exc_info()[1] - print "Passport. loadExternalModule. Flow will be driven entirely by routines of main passport script" - return None - - - def processKeyStoreProperties(self, attrs): - file = attrs.get("key_store_file") - password = attrs.get("key_store_password") - - if file != None and password != None: - file = file.getValue2() - password = password.getValue2() - - if StringHelper.isNotEmpty(file) and StringHelper.isNotEmpty(password): - self.keyStoreFile = file - self.keyStorePassword = password - return True - - print "Passport. readKeyStoreProperties. Properties key_store_file or key_store_password not found or empty" - return False - - - def getCustomAuthzParameter(self, simpleCustProperty): - - customAuthzParameter = None - if simpleCustProperty != None: - prop = simpleCustProperty.getValue2() - if StringHelper.isNotEmpty(prop): - customAuthzParameter = prop - - if customAuthzParameter == None: - print "Passport. getCustomAuthzParameter. No custom param for OIDC authz request in script properties" - print "Passport. getCustomAuthzParameter. Passport flow cannot be initiated by doing an OpenID connect authorization request" - else: - print "Passport. getCustomAuthzParameter. Custom param for OIDC authz request in script properties: %s" % customAuthzParameter - - return customAuthzParameter - -# Configuration parsing - - def getPassportConfigDN(self): - - f = open('/etc/gluu/conf/jans.properties', 'r') - for line in f: - prop = line.split("=") - if prop[0] == "oxpassport_ConfigurationEntryDN": - prop.pop(0) - break - - f.close() - return "=".join(prop).strip() - - - def parseAllProviders(self): - - registeredProviders = {} - print "Passport. parseAllProviders. Adding providers" - entryManager = CdiUtil.bean(PersistenceEntryManager) - - config = LdapOxPassportConfiguration() - config = entryManager.find(config.getClass(), self.passportDN).getPassportConfiguration() - config = config.getProviders() if config != None else config - - if config != None and len(config) > 0: - for prvdetails in config: - if prvdetails.isEnabled(): - registeredProviders[prvdetails.getId()] = { - "emailLinkingSafe": prvdetails.isEmailLinkingSafe(), - "requestForEmail" : prvdetails.isRequestForEmail(), - "logo_img": prvdetails.getLogoImg(), - "displayName": prvdetails.getDisplayName(), - "type": prvdetails.getType() - } - - return registeredProviders - - - def parseProviderConfigs(self): - - registeredProviders = {} - try: - registeredProviders = self.parseAllProviders() - toRemove = [] - - for provider in registeredProviders: - if registeredProviders[provider]["type"] == "saml": - toRemove.append(provider) - else: - registeredProviders[provider]["saml"] = False - - for provider in toRemove: - registeredProviders.pop(provider) - - if len(registeredProviders.keys()) > 0: - print "Passport. parseProviderConfigs. Configured providers:", registeredProviders - else: - print "Passport. parseProviderConfigs. No providers registered yet" - except: - print "Passport. parseProviderConfigs. An error occurred while building the list of supported authentication providers", sys.exc_info()[1] - - self.registeredProviders = registeredProviders - -# Auxiliary routines - - def getProviderFromJson(self, providerJson): - - provider = None - try: - obj = json.loads(Base64Util.base64urldecodeToString(providerJson)) - provider = obj[self.providerKey] - except: - print "Passport. getProviderFromJson. Could not parse provided Json string. Returning None" - - return provider - - - def getPassportRedirectUrl(self, provider): - - # provider is assumed to exist in self.registeredProviders - url = None - try: - facesContext = CdiUtil.bean(FacesContext) - tokenEndpoint = "https://%s/passport/token" % facesContext.getExternalContext().getRequest().getServerName() - - httpService = CdiUtil.bean(HttpService) - httpclient = httpService.getHttpsClient() - - print "Passport. getPassportRedirectUrl. Obtaining token from passport at %s" % tokenEndpoint - resultResponse = httpService.executeGet(httpclient, tokenEndpoint, Collections.singletonMap("Accept", "text/json")) - httpResponse = resultResponse.getHttpResponse() - bytes = httpService.getResponseContent(httpResponse) - - response = httpService.convertEntityToString(bytes) - print "Passport. getPassportRedirectUrl. Response was %s" % httpResponse.getStatusLine().getStatusCode() - - tokenObj = json.loads(response) - url = "/passport/auth/%s/%s" % (provider, tokenObj["token_"]) - except: - print "Passport. getPassportRedirectUrl. Error building redirect URL: ", sys.exc_info()[1] - - return url - - - def validSignature(self, jwt): - - print "Passport. validSignature. Checking JWT token signature" - valid = False - - try: - appConfiguration = AppConfiguration() - appConfiguration.setWebKeysStorage(WebKeyStorage.KEYSTORE) - appConfiguration.setKeyStoreFile(self.keyStoreFile) - appConfiguration.setKeyStoreSecret(self.keyStorePassword) - appConfiguration.setKeyRegenerationEnabled(False) - - cryptoProvider = CryptoProviderFactory.getCryptoProvider(appConfiguration) - valid = cryptoProvider.verifySignature(jwt.getSigningInput(), jwt.getEncodedSignature(), jwt.getHeader().getKeyId(), - None, None, jwt.getHeader().getSignatureAlgorithm()) - except: - print "Exception: ", sys.exc_info()[1] - - print "Passport. validSignature. Validation result was %s" % valid - return valid - - - def jwtHasExpired(self, jwt): - # Check if jwt has expired - jwt_claims = jwt.getClaims() - try: - exp_date_timestamp = float(jwt_claims.getClaimAsString(JwtClaimName.EXPIRATION_TIME)) - exp_date = datetime.datetime.fromtimestamp(exp_date_timestamp) - hasExpired = exp_date < datetime.datetime.now() - except: - print "Exception: The JWT does not have '%s' attribute" % JwtClaimName.EXPIRATION_TIME - return False - - return hasExpired - - - def getUserProfile(self, jwt): - jwt_claims = jwt.getClaims() - user_profile_json = None - - try: - user_profile_json = CdiUtil.bean(EncryptionService).decrypt(jwt_claims.getClaimAsString("data")) - user_profile = json.loads(user_profile_json) - except: - print "Passport. getUserProfile. Problem obtaining user profile json representation" - - return (user_profile, user_profile_json) - - - def attemptAuthentication(self, identity, user_profile, user_profile_json): - - uidKey = "uid" - if not self.checkRequiredAttributes(user_profile, [uidKey, self.providerKey]): - return False - - provider = user_profile[self.providerKey] - if not provider in self.registeredProviders: - print "Passport. attemptAuthentication. Identity Provider %s not recognized" % provider - return False - - uid = user_profile[uidKey][0] - externalUid = "passport-%s:%s" % (provider, uid) - - userService = CdiUtil.bean(UserService) - userByUid = userService.getUserByAttribute("oxExternalUid", externalUid, True) - - email = None - if "mail" in user_profile: - email = user_profile["mail"] - if len(email) == 0: - email = None - else: - email = email[0] - user_profile["mail"] = [ email ] - - if email == None and self.registeredProviders[provider]["requestForEmail"]: - print "Passport. attemptAuthentication. Email was not received" - - if userByUid != None: - # This avoids asking for the email over every login attempt - email = userByUid.getAttribute("mail") - if email != None: - print "Passport. attemptAuthentication. Filling missing email value with %s" % email - user_profile["mail"] = [ email ] - - if email == None: - # Store user profile in session and abort this routine - identity.setWorkingParameter("passport_user_profile", user_profile_json) - return True - - userByMail = None if email == None else userService.getUserByAttribute("mail", email) - - # Determine if we should add entry, update existing, or deny access - doUpdate = False - doAdd = False - if userByUid != None: - print "User with externalUid '%s' already exists" % externalUid - if userByMail == None: - doUpdate = True - else: - if userByMail.getUserId() == userByUid.getUserId(): - doUpdate = True - else: - print "Users with externalUid '%s' and mail '%s' are different. Access will be denied. Impersonation attempt?" % (externalUid, email) - self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email value corresponds to an already existing provisioned account") - else: - if userByMail == None: - doAdd = True - elif self.registeredProviders[provider]["emailLinkingSafe"]: - - tmpList = userByMail.getAttributeValues("oxExternalUid") - tmpList = ArrayList() if tmpList == None else ArrayList(tmpList) - tmpList.add(externalUid) - userByMail.setAttribute("oxExternalUid", tmpList, True) - - userByUid = userByMail - print "External user supplying mail %s will be linked to existing account '%s'" % (email, userByMail.getUserId()) - doUpdate = True - else: - print "An attempt to supply an email of an existing user was made. Turn on 'emailLinkingSafe' if you want to enable linking" - self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email value corresponds to an already existing account. If you already have a username and password use those instead of an external authentication site to get access.") - - username = None - try: - if doUpdate: - username = userByUid.getUserId() - print "Passport. attemptAuthentication. Updating user %s" % username - self.updateUser(userByUid, user_profile, userService) - elif doAdd: - print "Passport. attemptAuthentication. Creating user %s" % externalUid - newUser = self.addUser(externalUid, user_profile, userService) - username = newUser.getUserId() - except: - print "Exception: ", sys.exc_info()[1] - print "Passport. attemptAuthentication. Authentication failed" - return False - - if username == None: - print "Passport. attemptAuthentication. Authentication attempt was rejected" - return False - else: - logged_in = CdiUtil.bean(AuthenticationService).authenticate(username) - print "Passport. attemptAuthentication. Authentication for %s returned %s" % (username, logged_in) - return logged_in - - - def setMessageError(self, severity, msg): - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.setKeepMessages() - facesMessages.clear() - facesMessages.add(severity, msg) - - - def checkRequiredAttributes(self, profile, attrs): - - for attr in attrs: - if (not attr in profile) or len(profile[attr]) == 0: - print "Passport. checkRequiredAttributes. Attribute '%s' is missing in profile" % attr - return False - return True - - - def addUser(self, externalUid, profile, userService): - - newUser = User() - #Fill user attrs - newUser.setAttribute("oxExternalUid", externalUid, True) - self.fillUser(newUser, profile) - newUser = userService.addUser(newUser, True) - return newUser - - - def updateUser(self, foundUser, profile, userService): - - # when this is false, there might still some updates taking place (e.g. not related to profile attrs released by external provider) - if (not self.skipProfileUpdate): - self.fillUser(foundUser, profile) - userService.updateUser(foundUser) - - - def fillUser(self, foundUser, profile): - - for attr in profile: - # "provider" is disregarded if part of mapping - if attr != self.providerKey: - values = profile[attr] - print "%s = %s" % (attr, values) - foundUser.setAttribute(attr, values) - - if attr == "mail": - oxtrustMails = [] - for mail in values: - oxtrustMails.append('{"value":"%s","primary":false}' % mail) - foundUser.setAttribute("oxTrustEmail", oxtrustMails) diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/README.md b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/README.md deleted file mode 100644 index f6057707858..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/README.md +++ /dev/null @@ -1,10 +0,0 @@ -Passport is a person authentication module for oxAuth that enables [Google+ Authentication](https://www.google.com), [Twitter Authentication](https://www.twitter.com), [Facebook Authentication](https://www.facebook.com) etc. for user authentication. - -The module has a few properties: - - 1) generic_remote_attributes_list - It's mandatory property. Comma separated list of attribute names. Specify list of User claims(attributes) which script should use to map to local attributes. The count of attributes in this property should be equal to count attributes in generic_local_attributes_list property. -Example: `username, email, name, name, givenName, familyName, provider` - - 2) generic_local_attributes_list - It's mandatory property. Comma separated list of attribute names. Specify list of local attributes mapped from passport userInfo response. The count of attributes in this property should be equal to count attributes in generic_remote_attributes_list property. Local attributes list should contains next mandatory attributes: uid, mail, givenName, sn, cn. -Example: `uid, mail, cn, displayName, givenName, sn, provider` - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/sample/passport_script_entry.ldif b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/sample/passport_script_entry.ldif deleted file mode 100644 index 7142616ea58..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/passport/sample/passport_script_entry.ldif +++ /dev/null @@ -1,16 +0,0 @@ -dn: inum=@!1111!2FDB.CF02,ou=scripts,o=gluu -objectClass: oxCustomScript -objectClass: top -description: Passport authentication module -displayName: passport -gluuStatus: false -inum: @!1111!2FDB.CF02 -oxConfigurationProperty: {"value1":"generic_remote_attributes_list","value2":"username, email, name, name, givenName, familyName, provider","description":""} -oxConfigurationProperty: {"value1":"generic_local_attributes_list","value2":"uid, mail, cn, displayName, givenName, sn, provider","description":""} -oxLevel: 60 -oxModuleProperty: {"value1":"usage_type","value2":"interactive","description":""} -oxModuleProperty: {"value1":"location_type","value2":"ldap","description":""} -oxRevision: 1 -oxScript:: -oxScriptType: person_authentication -programmingLanguage: python diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/phonefactor/pflogin.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/phonefactor/pflogin.xhtml deleted file mode 100644 index 75fb26f69c7..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/phonefactor/pflogin.xhtml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - #{msgs['phonefactor.pageTitle']} - - -
- - - -
-
-
\ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/postauthn/postauthn.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/postauthn/postauthn.py deleted file mode 100644 index 575acd35ccf..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/postauthn/postauthn.py +++ /dev/null @@ -1,53 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Zabrovarnyy -# -# -from __future__ import print_function - -from io.jans.model.custom.script.type.postauthn import PostAuthnType - -class PostAuthn(PostAuthnType): - - def __init__(self, currentTimeMillis): - """Construct class. - - Args: - currentTimeMillis (int): current time in miliseconds - """ - self.currentTimeMillis = currentTimeMillis - - @classmethod - def init(cls, customScript, configurationAttributes): - print("Post Authn script. Initializing ...") - print("Post Authn script. Initialized successfully") - - return True - - @classmethod - def destroy(cls, configurationAttributes): - print("Post Authn script. Destroying ...") - print("Post Authn script. Destroyed successfully") - return True - - @classmethod - def getApiVersion(cls): - return 11 - - # This method is called during Authorization Request at Authorization Endpoint. - # If True is returned, session is set as unauthenticated and user is send for authentication. - # Note : - # context is reference of io.jans.as.server.service.external.context.ExternalPostAuthnContext(in https://github.com/GluuFederation/oxauth project, ) - @classmethod - def forceReAuthentication(cls, context): - return False - - # This method is called during Authorization Request at Authorization Endpoint. - # If True is returned user is send for Authorization. By default if client is "Pre-Authorized" or "Client Persist Authorizations" is on, authorization is skipped. - # This script has higher priority and can cancel Pre-Authorization and persisted authorizations. - # Note : - # context is reference of io.jans.as.server.service.external.context.ExternalPostAuthnContext(in https://github.com/GluuFederation/oxauth project, ) - @classmethod - def forceAuthorization(cls, context): - return False diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/registration/register.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/registration/register.py deleted file mode 100644 index 3e1cce023ce..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/registration/register.py +++ /dev/null @@ -1,181 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.jsf2.message import FacesMessages -from jakarta.faces.application import FacesMessage -from io.jans.util import StringHelper, ArrayHelper -from java.util import Arrays, ArrayList, HashMap, IdentityHashMap -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import UserService, ClientService, AuthenticationService -from io.jans.util import StringHelper -from org.gluu.oxauth.model.common import User -from io.jans.as.server.util import ServerUtil -from io.jans.jsf2.service import FacesService -from org.gluu.oxauth.model.util import Base64Util -from org.python.core.util import StringUtil -from io.jans.as.server.service.net import HttpService -from jakarta.faces.context import FacesContext - -import java - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Registration. Initialization" - print "Registration. Initialized successfully" - if (configurationAttributes.containsKey("generic_register_attributes_list") and - configurationAttributes.containsKey("generic_local_attributes_list")): - - remoteAttributesList = configurationAttributes.get("generic_register_attributes_list").getValue2() - if (StringHelper.isEmpty(remoteAttributesList)): - print "Registration: Initialization. The property generic_register_attributes_list is empty" - return False - - localAttributesList = configurationAttributes.get("generic_local_attributes_list").getValue2() - if (StringHelper.isEmpty(localAttributesList)): - print "Registration: Initialization. The property generic_local_attributes_list is empty" - return False - - self.attributesMapping = self.prepareAttributesMapping(remoteAttributesList, localAttributesList) - if (self.attributesMapping == None): - print "Registration: Initialization. The attributes mapping isn't valid" - return False - - return True - - - def destroy(self, configurationAttributes): - print "Registration. Destroy" - print "Registration. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - def getUserValueFromAuth(self, remote_attr, requestParameters): - try: - toBeFeatched = "loginForm:" + remote_attr - return ServerUtil.getFirstValue(requestParameters, toBeFeatched) - except Exception, err: - print("Registration: Exception inside getUserValueFromAuth " + str(err)) - - def authenticate(self, configurationAttributes, requestParameters, step): - print "Registration. Authenticate for step 1" - userService = CdiUtil.bean(UserService) - authenticationService = CdiUtil.bean(AuthenticationService) - - if (StringHelper.isEmptyString(self.getUserValueFromAuth("email", requestParameters))): - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.setKeepMessages() - facesMessages.add(FacesMessage.SEVERITY_ERROR, "Please provide your email.") - return False - - if (StringHelper.isEmptyString(self.getUserValueFromAuth("pwd", requestParameters))): - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.setKeepMessages() - facesMessages.add(FacesMessage.SEVERITY_ERROR, "Please provide password.") - return False - - - - foundUser = userService.getUserByAttribute("mail", self.getUserValueFromAuth("email", requestParameters)) - if (foundUser == None): - newUser = User() - for attributesMappingEntry in self.attributesMapping.entrySet(): - remoteAttribute = attributesMappingEntry.getKey() - localAttribute = attributesMappingEntry.getValue() - localAttributeValue = self.getUserValueFromAuth(remoteAttribute, requestParameters) - if ((localAttribute != None) & (localAttributeValue != "undefined")): - print localAttribute + localAttributeValue - newUser.setAttribute(localAttribute, localAttributeValue) - - try: - foundUser = userService.addUser(newUser, True) - foundUserName = foundUser.getUserId() - print("Registration: Found user name " + foundUserName) - userAuthenticated = authenticationService.authenticate(foundUserName) - print("Registration: User added successfully and isUserAuthenticated = " + str(userAuthenticated)) - except Exception, err: - print("Registration: Error in adding user:" + str(err)) - return False - return userAuthenticated - else: - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.setKeepMessages() - facesMessages.add(FacesMessage.SEVERITY_ERROR, "User with same email already exists!") - return False - - - - def prepareForStep(self, configurationAttributes, requestParameters, step): - if (step == 1): - print "Registration. Prepare for Step 1" - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - return 1 - - def getPageForStep(self, configurationAttributes, step): - if step == 1: - return "/auth/register/register.xhtml" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - - def prepareAttributesMapping(self, remoteAttributesList, localAttributesList): - try: - remoteAttributesListArray = StringHelper.split(remoteAttributesList, ",") - if (ArrayHelper.isEmpty(remoteAttributesListArray)): - print("Registration: PrepareAttributesMapping. There is no attributes specified in remoteAttributesList property") - return None - - localAttributesListArray = StringHelper.split(localAttributesList, ",") - if (ArrayHelper.isEmpty(localAttributesListArray)): - print("Registration: PrepareAttributesMapping. There is no attributes specified in localAttributesList property") - return None - - if (len(remoteAttributesListArray) != len(localAttributesListArray)): - print("Registration: PrepareAttributesMapping. The number of attributes in remoteAttributesList and localAttributesList isn't equal") - return None - - attributeMapping = IdentityHashMap() - containsUid = False - i = 0 - count = len(remoteAttributesListArray) - while (i < count): - remoteAttribute = StringHelper.toLowerCase(remoteAttributesListArray[i]) - localAttribute = StringHelper.toLowerCase(localAttributesListArray[i]) - attributeMapping.put(remoteAttribute, localAttribute) - - i = i + 1 - - return attributeMapping - except Exception, err: - print("Registration: Exception inside prepareAttributesMapping " + str(err)) diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml-passport/SamlPassportAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml-passport/SamlPassportAuthenticator.py deleted file mode 100644 index 7d823d55a4e..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml-passport/SamlPassportAuthenticator.py +++ /dev/null @@ -1,826 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Jose Gonzalez -# Author: Yuriy Movchan -# Author: Christian Eland -# - -from io.jans.jsf2.service import FacesService -from io.jans.jsf2.message import FacesMessages - -from org.gluu.oxauth.model.common import User, WebKeyStorage -from org.gluu.oxauth.model.configuration import AppConfiguration -from org.gluu.oxauth.model.crypto import CryptoProviderFactory -from org.gluu.oxauth.model.jwt import Jwt, JwtClaimName -from org.gluu.oxauth.model.util import Base64Util -from io.jans.as.server.service import AppInitializer, AuthenticationService -from io.jans.as.server.service.common import UserService, EncryptionService -from org.gluu.oxauth.model.authorize import AuthorizeRequestParam -from io.jans.as.server.service.net import HttpService -from io.jans.as.server.security import Identity -from io.jans.as.server.util import ServerUtil -from org.gluu.config.oxtrust import LdapOxPassportConfiguration -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.orm import PersistenceEntryManager -from io.jans.service.cdi.util import CdiUtil -from io.jans.util import StringHelper -from java.util import ArrayList, Arrays, Collections, HashSet -from org.gluu.oxauth.model.exception import InvalidJwtException -from jakarta.faces.application import FacesMessage -from jakarta.faces.context import FacesContext - -import json -import sys -import datetime -import base64 - - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - - print "Passport. init called" - - self.extensionModule = self.loadExternalModule(configurationAttributes.get("extension_module")) - extensionResult = self.extensionInit(configurationAttributes) - if extensionResult != None: - return extensionResult - - print "Passport. init. Behaviour is inbound SAML" - success = self.processKeyStoreProperties(configurationAttributes) - - if success: - self.providerKey = "provider" - self.customAuthzParameter = self.getCustomAuthzParameter(configurationAttributes.get("authz_req_param_provider")) - self.passportDN = self.getPassportConfigDN() - print "Passport. init. Initialization success" - else: - print "Passport. init. Initialization failed" - return success - - - def destroy(self, configurationAttributes): - print "Passport. destroy called" - return True - - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - - def authenticate(self, configurationAttributes, requestParameters, step): - - extensionResult = self.extensionAuthenticate(configurationAttributes, requestParameters, step) - if extensionResult != None: - return extensionResult - - print "Passport. authenticate for step %s called" % str(step) - identity = CdiUtil.bean(Identity) - - # Loading self.registeredProviders in case passport destroyed - if not hasattr(self,'registeredProviders'): - print "Passport. Fetching registered providers." - self.parseProviderConfigs() - - if step == 1: - - jwt_param = None - - if self.isInboundFlow(identity): - # if is idp-initiated inbound flow - print "Passport. authenticate for step 1. Detected idp-initiated inbound Saml flow" - # get request from session attributes - jwt_param = identity.getSessionId().getSessionAttributes().get(AuthorizeRequestParam.STATE) - print "jwt_param = %s" % jwt_param - # now jwt_param != None - - - - if jwt_param == None: - # gets jwt parameter "user" sent after authentication by passport (if exists) - jwt_param = ServerUtil.getFirstValue(requestParameters, "user") - - - if jwt_param != None: - # and now that the jwt_param user exists... - print "Passport. authenticate for step 1. JWT user profile token found" - - if self.isInboundFlow(identity): - jwt_param = base64.urlsafe_b64decode(str(jwt_param+'==')) - - # Parse JWT and validate - jwt = Jwt.parse(jwt_param) - - if not self.validSignature(jwt): - return False - - if self.jwtHasExpired(jwt): - return False - - # Gets user profile as string and json using the information on JWT - (user_profile, jsonp) = self.getUserProfile(jwt) - - if user_profile == None: - return False - - sessionAttributes = identity.getSessionId().getSessionAttributes() - self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get("skipPassportProfileUpdate"), "true") - - return self.attemptAuthentication(identity, user_profile, jsonp) - - #See passportlogin.xhtml - provider = ServerUtil.getFirstValue(requestParameters, "loginForm:provider") - - if StringHelper.isEmpty(provider): - - #it's username + passw auth - print "Passport. authenticate for step 1. Basic authentication detected" - logged_in = False - - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - authenticationService = CdiUtil.bean(AuthenticationService) - logged_in = authenticationService.authenticate(user_name, user_password) - - print "Passport. authenticate for step 1. Basic authentication returned: %s" % logged_in - return logged_in - - - - elif provider in self.registeredProviders: - # user selected provider - # it's a recognized external IDP - - identity.setWorkingParameter("selectedProvider", provider) - print "Passport. authenticate for step 1. Retrying step 1" - - #see prepareForStep (step = 1) - return True - - if step == 2: - mail = ServerUtil.getFirstValue(requestParameters, "loginForm:email") - jsonp = identity.getWorkingParameter("passport_user_profile") - - if mail == None: - self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email was missing in user profile") - elif jsonp != None: - # Completion of profile takes place - user_profile = json.loads(jsonp) - user_profile["mail"] = [ mail ] - - return self.attemptAuthentication(identity, user_profile, jsonp) - - print "Passport. authenticate for step 2. Failed: expected mail value in HTTP request and json profile in session" - return False - - - def prepareForStep(self, configurationAttributes, requestParameters, step): - - extensionResult = self.extensionPrepareForStep(configurationAttributes, requestParameters, step) - if extensionResult != None: - return extensionResult - - print "Passport. prepareForStep called %s" % str(step) - identity = CdiUtil.bean(Identity) - - if step == 1: - #re-read the strategies config (for instance to know which strategies have enabled the email account linking) - self.parseProviderConfigs() - identity.setWorkingParameter("externalProviders", json.dumps(self.registeredProviders)) - - providerParam = self.customAuthzParameter - url = None - - sessionAttributes = identity.getSessionId().getSessionAttributes() - self.skipProfileUpdate = StringHelper.equalsIgnoreCase(sessionAttributes.get("skipPassportProfileUpdate"), "true") - - #this param could have been set previously in authenticate step if current step is being retried - provider = identity.getWorkingParameter("selectedProvider") - print "prepareForStep %s - provider = %s" % (str(step), str(provider)) - - # if there is a selectedProvider - if provider != None: - - # get the redirect URL to use at facesService.redirectToExternalURL() that sends /passport/auth// - url = self.getPassportRedirectUrl(provider) - print "prepareForStep %s - url = %s" % (str(step), url) - - # sets selectedProvider back to None - identity.setWorkingParameter("selectedProvider", None) - - # if there is customAuthzParameter - elif providerParam != None: - - - # get it from sessionAtributes - paramValue = sessionAttributes.get(providerParam) - - #if exists - if paramValue != None: - print "Passport. prepareForStep. Found value in custom param of authorization request: %s" % paramValue - provider = self.getProviderFromJson(paramValue) - - if provider == None: - print "Passport. prepareForStep. A provider value could not be extracted from custom authorization request parameter" - elif not provider in self.registeredProviders: - print "Passport. prepareForStep. Provider '%s' not part of known configured IDPs/OPs" % provider - else: - url = self.getPassportRedirectUrl(provider) - - - # if no provider selected yet... - if url == None: - print "Passport. prepareForStep. A page to manually select an identity provider will be shown" - - # else already got the /passport/auth// url... - else: - - facesService = CdiUtil.bean(FacesService) - - # redirects to Passport getRedirectURL - sends browser to IDP. - print "Passport. Redirecting to external url: %s" + url - - facesService.redirectToExternalURL(url) - - return True - - - def getExtraParametersForStep(self, configurationAttributes, step): - print "Passport. getExtraParametersForStep called for step %s" % str(step) - if step == 1: - return Arrays.asList("selectedProvider", "externalProviders") - elif step == 2: - return Arrays.asList("passport_user_profile") - return None - - - def getCountAuthenticationSteps(self, configurationAttributes): - print "Passport. getCountAuthenticationSteps called" - identity = CdiUtil.bean(Identity) - if identity.getWorkingParameter("passport_user_profile") != None: - return 2 - return 1 - - - def getPageForStep(self, configurationAttributes, step): - print "Passport. getPageForStep called" - - extensionResult = self.extensionGetPageForStep(configurationAttributes, step) - if extensionResult != None: - return extensionResult - - if step == 1: - identity = CdiUtil.bean(Identity) - print "Passport. getPageForStep. Entered if step ==1" - if self.isInboundFlow(identity): - print "Passport. getPageForStep for step 1. Detected inbound Saml flow" - return "/postlogin.xhtml" - print "Passport. getPageForStep 1. NormalFlow, returning passportlogin.xhtml" - return "/auth/passport/passportlogin.xhtml" - - return "/auth/passport/passportpostlogin.xhtml" - - - def getNextStep(self, configurationAttributes, requestParameters, step): - if step == 1: - identity = CdiUtil.bean(Identity) - provider = identity.getWorkingParameter("selectedProvider") - if provider != None: - return 1 - - return -1 - - - def logout(self, configurationAttributes, requestParameters): - return True - -# Extension module related functions - - def extensionInit(self, configurationAttributes): - - if self.extensionModule == None: - return None - return self.extensionModule.init(configurationAttributes) - - - def extensionAuthenticate(self, configurationAttributes, requestParameters, step): - - if self.extensionModule == None: - return None - return self.extensionModule.authenticate(configurationAttributes, requestParameters, step) - - - def extensionPrepareForStep(self, configurationAttributes, requestParameters, step): - - if self.extensionModule == None: - return None - return self.extensionModule.prepareForStep(configurationAttributes, requestParameters, step) - - - def extensionGetPageForStep(self, configurationAttributes, step): - - if self.extensionModule == None: - return None - return self.extensionModule.getPageForStep(configurationAttributes, step) - -# Initalization routines - - def loadExternalModule(self, simpleCustProperty): - - if simpleCustProperty != None: - print "Passport. loadExternalModule. Loading passport extension module..." - moduleName = simpleCustProperty.getValue2() - try: - module = __import__(moduleName) - return module - except: - print "Passport. loadExternalModule. Failed to load module %s" % moduleName - print "Exception: ", sys.exc_info()[1] - print "Passport. loadExternalModule. Flow will be driven entirely by routines of main passport script" - return None - - - def processKeyStoreProperties(self, attrs): - file = attrs.get("key_store_file") - password = attrs.get("key_store_password") - - if file != None and password != None: - file = file.getValue2() - password = password.getValue2() - - if StringHelper.isNotEmpty(file) and StringHelper.isNotEmpty(password): - self.keyStoreFile = file - self.keyStorePassword = password - return True - - print "Passport. readKeyStoreProperties. Properties key_store_file or key_store_password not found or empty" - return False - - - def getCustomAuthzParameter(self, simpleCustProperty): - - customAuthzParameter = None - if simpleCustProperty != None: - prop = simpleCustProperty.getValue2() - if StringHelper.isNotEmpty(prop): - customAuthzParameter = prop - - if customAuthzParameter == None: - print "Passport. getCustomAuthzParameter. No custom param for OIDC authz request in script properties" - print "Passport. getCustomAuthzParameter. Passport flow cannot be initiated by doing an OpenID connect authorization request" - else: - print "Passport. getCustomAuthzParameter. Custom param for OIDC authz request in script properties: %s" % customAuthzParameter - - return customAuthzParameter - -# Configuration parsing - - def getPassportConfigDN(self): - - f = open('/etc/gluu/conf/gluu.properties', 'r') - for line in f: - prop = line.split("=") - if prop[0] == "oxpassport_ConfigurationEntryDN": - prop.pop(0) - break - - f.close() - return "=".join(prop).strip() - - - def parseAllProviders(self): - - registeredProviders = {} - print "Passport. parseAllProviders. Adding providers" - entryManager = CdiUtil.bean(PersistenceEntryManager) - - config = LdapOxPassportConfiguration() - config = entryManager.find(config.getClass(), self.passportDN).getPassportConfiguration() - config = config.getProviders() if config != None else config - - if config != None and len(config) > 0: - for prvdetails in config: - if prvdetails.isEnabled(): - registeredProviders[prvdetails.getId()] = { - "emailLinkingSafe": prvdetails.isEmailLinkingSafe(), - "requestForEmail" : prvdetails.isRequestForEmail(), - "logo_img": prvdetails.getLogoImg(), - "displayName": prvdetails.getDisplayName(), - "type": prvdetails.getType() - } - - return registeredProviders - - - def parseProviderConfigs(self): - - registeredProviders = {} - try: - registeredProviders = self.parseAllProviders() - toRemove = [] - - for provider in registeredProviders: - if registeredProviders[provider]["type"] != "saml": - toRemove.append(provider) - else: - registeredProviders[provider]["saml"] = True - - for provider in toRemove: - registeredProviders.pop(provider) - - - if len(registeredProviders.keys()) > 0: - print "Passport. parseProviderConfigs. Configured providers:", registeredProviders - else: - print "Passport. parseProviderConfigs. No providers registered yet" - except: - print "Passport. parseProviderConfigs. An error occurred while building the list of supported authentication providers", sys.exc_info()[1] - - - print "parseProviderConfigs - registeredProviders = %s" % str(registeredProviders) - self.registeredProviders = registeredProviders - print "parseProviderConfigs - self.registeredProviders = %s" % str(self.registeredProviders) - -# Auxiliary routines - - def getProviderFromJson(self, providerJson): - - provider = None - try: - obj = json.loads(Base64Util.base64urldecodeToString(providerJson)) - provider = obj[self.providerKey] - except: - print "Passport. getProviderFromJson. Could not parse provided Json string. Returning None" - - return provider - - - def getPassportRedirectUrl(self, provider): - - # provider is assumed to exist in self.registeredProviders - url = None - try: - facesContext = CdiUtil.bean(FacesContext) - tokenEndpoint = "https://%s/passport/token" % facesContext.getExternalContext().getRequest().getServerName() - - httpService = CdiUtil.bean(HttpService) - httpclient = httpService.getHttpsClient() - - print "Passport. getPassportRedirectUrl. Obtaining token from passport at %s" % tokenEndpoint - resultResponse = httpService.executeGet(httpclient, tokenEndpoint, Collections.singletonMap("Accept", "text/json")) - httpResponse = resultResponse.getHttpResponse() - - bytes = httpService.getResponseContent(httpResponse) - - response = httpService.convertEntityToString(bytes) - print "Passport. getPassportRedirectUrl. Response was %s" % httpResponse.getStatusLine().getStatusCode() - - tokenObj = json.loads(response) - - url = "/passport/auth/%s/%s" % (provider, tokenObj["token_"]) - - except: - print "Passport. getPassportRedirectUrl. Error building redirect URL: ", sys.exc_info()[1] - - return url - - - def validSignature(self, jwt): - - print "Passport. validSignature. Checking JWT token signature" - valid = False - - try: - - appConfiguration = AppConfiguration() - appConfiguration.setWebKeysStorage(WebKeyStorage.KEYSTORE) - appConfiguration.setKeyStoreFile(self.keyStoreFile) - appConfiguration.setKeyStoreSecret(self.keyStorePassword) - appConfiguration.setKeyRegenerationEnabled(False) - - cryptoProvider = CryptoProviderFactory.getCryptoProvider(appConfiguration) - - - alg_string = str(jwt.getHeader().getSignatureAlgorithm()) - signature_string = str(jwt.getEncodedSignature()) - - if alg_string == "none" or alg_string == "None" or alg_string == "NoNe" or alg_string == "nONE" or alg_string == "NONE" or alg_string == "NonE" or alg_string == "nOnE": - # blocks none attack - - print "WARNING: JWT Signature algorithm is none" - valid = False - - elif alg_string != "RS512": - # blocks anything that's not RS512 - - print "WARNING: JWT Signature algorithm is NOT RS512" - valid = False - - elif signature_string == "" : - # blocks empty signature string - print "WARNING: JWT Signature not sent" - valid = False - - else: - - # class extends AbstractCryptoProvider - ''' on version 4.2 .getAlgorithm() method was renamed to .getSignatureAlgorithm() - for older versions: - valid = cryptoProvider.verifySignature(jwt.getSigningInput(), jwt.getEncodedSignature(), jwt.getHeader().getKeyId(), - None, None, jwt.getHeader().getAlgorithm()) - ''' - - # working on 4.2: - valid = cryptoProvider.verifySignature(jwt.getSigningInput(), jwt.getEncodedSignature(), jwt.getHeader().getKeyId(), - None, None, jwt.getHeader().getSignatureAlgorithm()) - - except: - print "Exception: ", sys.exc_info()[1] - - print "Passport. validSignature. Validation result was %s" % valid - - return valid - - - def jwtHasExpired(self, jwt): - # Check if jwt has expired - jwt_claims = jwt.getClaims() - try: - exp_date_timestamp = float(jwt_claims.getClaimAsString(JwtClaimName.EXPIRATION_TIME)) - exp_date = datetime.datetime.fromtimestamp(exp_date_timestamp) - hasExpired = exp_date < datetime.datetime.now() - except: - print "Exception: The JWT does not have '%s' attribute" % JwtClaimName.EXPIRATION_TIME - return False - - return hasExpired - - - def getUserProfile(self, jwt): - - # getClaims method located at org.gluu.oxauth.model.token.JsonWebResponse.java as a org.gluu.oxauth.model.jwt.JwtClaims object - jwt_claims = jwt.getClaims() - - user_profile_json = None - - try: - # public String getClaimAsString(String key) - user_profile_json = CdiUtil.bean(EncryptionService).decrypt(jwt_claims.getClaimAsString("data")) - - user_profile = json.loads(user_profile_json) - except: - print "Passport. getUserProfile. Problem obtaining user profile json representation" - - return (user_profile, user_profile_json) - - - def attemptAuthentication(self, identity, user_profile, user_profile_json): - - print "Entered attemptAuthentication..." - uidKey = "uid" - if not self.checkRequiredAttributes(user_profile, [uidKey, self.providerKey]): - return False - - provider = user_profile[self.providerKey] - print "user_profile[self.providerKey] = %s" % str(user_profile[self.providerKey]) - if not provider in self.registeredProviders: - print "Entered if note provider in self.registeredProviers:" - print "Passport. attemptAuthentication. Identity Provider %s not recognized" % provider - return False - - print "attemptAuthentication. user_profile = %s" % user_profile - print "user_profile[uidKey] = %s" % user_profile[uidKey] - uid = user_profile[uidKey][0] - print "attemptAuthentication - uid = %s" % uid - externalUid = "passport-%s:%s:%s" % ("saml", provider, uid) - - userService = CdiUtil.bean(UserService) - userByUid = self.getUserByExternalUid(uid, provider, userService) - - email = None - if "mail" in user_profile: - email = user_profile["mail"] - if len(email) == 0: - email = None - else: - email = email[0] - user_profile["mail"] = [ email ] - - if email == None and self.registeredProviders[provider]["requestForEmail"]: - print "Passport. attemptAuthentication. Email was not received" - - if userByUid != None: - # This avoids asking for the email over every login attempt - email = userByUid.getAttribute("mail") - if email != None: - print "Passport. attemptAuthentication. Filling missing email value with %s" % email - user_profile["mail"] = [ email ] - - if email == None: - # Store user profile in session and abort this routine - identity.setWorkingParameter("passport_user_profile", user_profile_json) - return True - - userByMail = None if email == None else userService.getUserByAttribute("mail", email) - - # Determine if we should add entry, update existing, or deny access - doUpdate = False - doAdd = False - if userByUid != None: - print "User with externalUid '%s' already exists" % externalUid - if userByMail == None: - doUpdate = True - else: - if userByMail.getUserId() == userByUid.getUserId(): - doUpdate = True - else: - print "Users with externalUid '%s' and mail '%s' are different. Access will be denied. Impersonation attempt?" % (externalUid, email) - self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email value corresponds to an already existing provisioned account") - else: - if userByMail == None: - doAdd = True - elif self.registeredProviders[provider]["emailLinkingSafe"]: - - tmpList = userByMail.getAttributeValues("oxExternalUid") - tmpList = ArrayList() if tmpList == None else ArrayList(tmpList) - tmpList.add(externalUid) - userByMail.setAttribute("oxExternalUid", tmpList, True) - - userByUid = userByMail - print "External user supplying mail %s will be linked to existing account '%s'" % (email, userByMail.getUserId()) - doUpdate = True - else: - print "An attempt to supply an email of an existing user was made. Turn on 'emailLinkingSafe' if you want to enable linking" - self.setMessageError(FacesMessage.SEVERITY_ERROR, "Email value corresponds to an already existing account. If you already have a username and password use those instead of an external authentication site to get access.") - - username = None - try: - if doUpdate: - username = userByUid.getUserId() - print "Passport. attemptAuthentication. Updating user %s" % username - self.updateUser(userByUid, user_profile, userService) - elif doAdd: - print "Passport. attemptAuthentication. Creating user %s" % externalUid - newUser = self.addUser(externalUid, user_profile, userService) - username = newUser.getUserId() - except: - print "Exception: ", sys.exc_info()[1] - print "Passport. attemptAuthentication. Authentication failed" - return False - - if username == None: - print "Passport. attemptAuthentication. Authentication attempt was rejected" - return False - else: - logged_in = CdiUtil.bean(AuthenticationService).authenticate(username) - print "Passport. attemptAuthentication. Authentication for %s returned %s" % (username, logged_in) - return logged_in - - - def getUserByExternalUid(self, uid, provider, userService): - newFormat = "passport-%s:%s:%s" % ("saml", provider, uid) - user = userService.getUserByAttribute("oxExternalUid", newFormat, True) - - if user == None: - oldFormat = "passport-%s:%s" % ("saml", uid) - user = userService.getUserByAttribute("oxExternalUid", oldFormat, True) - - if user != None: - # Migrate to newer format - list = HashSet(user.getAttributeValues("oxExternalUid")) - list.remove(oldFormat) - list.add(newFormat) - user.setAttribute("oxExternalUid", ArrayList(list), True) - print "Migrating user's oxExternalUid to newer format 'passport-saml:provider:uid'" - userService.updateUser(user) - - return user - - - def setMessageError(self, severity, msg): - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.setKeepMessages() - facesMessages.clear() - facesMessages.add(severity, msg) - - - def checkRequiredAttributes(self, profile, attrs): - - for attr in attrs: - if (not attr in profile) or len(profile[attr]) == 0: - print "Passport. checkRequiredAttributes. Attribute '%s' is missing in profile" % attr - return False - return True - - - def addUser(self, externalUid, profile, userService): - print "Passport. Entered addUser()." - print "Passport. addUser. externalUid = %s" % externalUid - print "Passport. addUser. profile = %s" % profile - newUser = User() - #Fill user attrs - newUser.setAttribute("oxExternalUid", externalUid, True) - self.fillUser(newUser, profile) - newUser = userService.addUser(newUser, True) - return newUser - - - def updateUser(self, foundUser, profile, userService): - # when this is false, there might still some updates taking place (e.g. not related to profile attrs released by external provider) - if (not self.skipProfileUpdate): - self.fillUser(foundUser, profile) - userService.updateUser(foundUser) - - - def fillUser(self, foundUser, profile): - print - print "Passport. Entered fillUser()." - print "Passport. fillUser. foundUser = %s" % foundUser - print "Passport. fillUser. profile = %s" % profile - for attr in profile: - # "provider" is disregarded if part of mapping - if attr != self.providerKey: - values = profile[attr] - print "%s = %s" % (attr, values) - foundUser.setAttribute(attr, values) - - if attr == "mail": - print "Passport. fillUser. entered if attr == mail" - oxtrustMails = [] - for mail in values: - oxtrustMails.append('{"value":"%s","primary":false}' % mail) - foundUser.setAttribute("oxTrustEmail", oxtrustMails) - -# IDP-initiated flow routines - - def isInboundFlow(self, identity): - print "passport. entered isInboundFlow" - - sessionId = identity.getSessionId() - print "passport. isInboundFlow. sessionId = %s" % sessionId - if sessionId == None: - print "passport. isInboundFlow. sessionId not found yet..." - # Detect mode if there is no session yet. It's needed for getPageForStep method - facesContext = CdiUtil.bean(FacesContext) - requestParameters = facesContext.getExternalContext().getRequestParameterMap() - print "passport. isInboundFlow. requestParameters = %s" % requestParameters - - authz_state = requestParameters.get(AuthorizeRequestParam.STATE) - print "passport. isInboundFlow. authz_state = %s" % authz_state - else: - authz_state = identity.getSessionId().getSessionAttributes().get(AuthorizeRequestParam.STATE) - - print "passport. IsInboundFlow. authz_state = %s" % authz_state - - # the replace above is workaround due a problem reported - # on issue: https://github.com/GluuFederation/gluu-passport/issues/95 - # TODO: Remove after fixed on JSF side - - b64url_decoded_auth_state = base64.urlsafe_b64decode(str(authz_state+'==')) - - # print "passport. IsInboundFlow. b64url_decoded_auth_state = %s" % str(b64url_decoded_auth_state) - print "passport. IsInboundFlow. self.isInboundJwt() = %s" % str(self.isInboundJwt(b64url_decoded_auth_state)) - if self.isInboundJwt(b64url_decoded_auth_state): - return True - - return False - - - def isInboundJwt(self, value): - if value == None: - return False - - try: - jwt = Jwt.parse(value) - print "passport.isInboundJwt. jwt = %s" % jwt - user_profile_json = CdiUtil.bean(EncryptionService).decrypt(jwt.getClaims().getClaimAsString("data")) - if StringHelper.isEmpty(user_profile_json): - return False - except InvalidJwtException: - return False - - except: - print("Unexpected error:", sys.exc_info()[0]) - return False - - return True - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/Gluu Inbound SAML Design (no Session).png b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/Gluu Inbound SAML Design (no Session).png deleted file mode 100644 index 14f67ddf172..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/Gluu Inbound SAML Design (no Session).png and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/SamlExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/SamlExternalAuthenticator.py deleted file mode 100644 index 5d38cbd3234..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/saml/SamlExternalAuthenticator.py +++ /dev/null @@ -1,793 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -import java -import json -from java.lang import StringBuilder -from jakarta.faces.context import FacesContext -from java.util import Arrays, ArrayList, HashMap, IdentityHashMap -from jakarta.faces.application import FacesMessage -from io.jans.jsf2.message import FacesMessages -from org.gluu.saml import SamlConfiguration, AuthRequest, Response -from org.gluu.ldap.model import CustomAttribute -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from org.gluu.oxauth.model.common import User -from io.jans.as.server.security import Identity -from io.jans.as.server.service import UserService, ClientService, AuthenticationService, AttributeService -from io.jans.as.server.service.net import HttpService -from io.jans.service.cdi.util import CdiUtil -from io.jans.util import StringHelper, ArrayHelper, Util -from io.jans.jsf2.service import FacesService - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "Asimba. Initialization" - - asimba_saml_certificate_file = configurationAttributes.get("asimba_saml_certificate_file").getValue2() - saml_idp_sso_target_url = configurationAttributes.get("saml_idp_sso_target_url").getValue2() - asimba_entity_id = configurationAttributes.get("asimba_entity_id").getValue2() - saml_use_authn_context = StringHelper.toBoolean(configurationAttributes.get("saml_use_authn_context").getValue2(), True) - if saml_use_authn_context: - saml_name_identifier_format = configurationAttributes.get("saml_name_identifier_format").getValue2() - else: - saml_name_identifier_format = None - - asimba_saml_certificate = self.loadCeritificate(asimba_saml_certificate_file) - if StringHelper.isEmpty(asimba_saml_certificate): - print "Asimba. Initialization. File with x509 certificate should be not empty" - return False - - samlConfiguration = SamlConfiguration() - - # Set the issuer of the authentication request. This would usually be the URL of the issuing web application - samlConfiguration.setIssuer(asimba_entity_id) - - # Tells the IdP to return a persistent identifier for the user - samlConfiguration.setNameIdentifierFormat(saml_name_identifier_format) - - # The URL at the Identity Provider where to the authentication request should be sent - samlConfiguration.setIdpSsoTargetUrl(saml_idp_sso_target_url) - - # Enablediable RequestedAuthnContext - samlConfiguration.setUseRequestedAuthnContext(saml_use_authn_context) - - # Load x509 certificate - samlConfiguration.loadCertificateFromString(asimba_saml_certificate) - - self.samlConfiguration = samlConfiguration - - self.generateNameId = False - if configurationAttributes.containsKey("saml_generate_name_id"): - self.generateNameId = StringHelper.toBoolean(configurationAttributes.get("saml_generate_name_id").getValue2(), False) - print "Asimba. Initialization. The property saml_generate_name_id is %s" % self.generateNameId - - self.updateUser = False - if configurationAttributes.containsKey("saml_update_user"): - self.updateUser = StringHelper.toBoolean(configurationAttributes.get("saml_update_user").getValue2(), False) - - print "Asimba. Initialization. The property saml_update_user is %s" % self.updateUser - - self.userObjectClasses = None - if configurationAttributes.containsKey("user_object_classes"): - self.userObjectClasses = self.prepareUserObjectClasses(configurationAttributes) - - self.userEnforceAttributesUniqueness = None - if configurationAttributes.containsKey("enforce_uniqueness_attr_list"): - self.userEnforceAttributesUniqueness = self.prepareUserEnforceUniquenessAttributes(configurationAttributes) - - self.attributesMapping = None - if configurationAttributes.containsKey("saml_idp_attributes_mapping"): - saml_idp_attributes_mapping = configurationAttributes.get("saml_idp_attributes_mapping").getValue2() - if StringHelper.isEmpty(saml_idp_attributes_mapping): - print "Asimba. Initialization. The property saml_idp_attributes_mapping is empty" - return False - - self.attributesMapping = self.prepareAttributesMapping(saml_idp_attributes_mapping) - if self.attributesMapping == None: - print "Asimba. Initialization. The attributes mapping isn't valid" - return False - - self.samlExtensionModule = None - if configurationAttributes.containsKey("saml_extension_module"): - saml_extension_module_name = configurationAttributes.get("saml_extension_module").getValue2() - try: - self.samlExtensionModule = __import__(saml_extension_module_name) - saml_extension_module_init_result = self.samlExtensionModule.init(configurationAttributes) - if not saml_extension_module_init_result: - return False - except ImportError, ex: - print "Asimba. Initialization. Failed to load saml_extension_module: '%s'" % saml_extension_module_name - print "Asimba. Initialization. Unexpected error:", ex - return False - - self.debugEnrollment = False - - print "Asimba. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "Asimba. Destroy" - print "Asimba. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - userService = CdiUtil.bean(UserService) - authenticationService = CdiUtil.bean(AuthenticationService) - - saml_map_user = False - saml_enroll_user = False - saml_enroll_all_user_attr = False - # Use saml_deployment_type only if there is no attributes mapping - if configurationAttributes.containsKey("saml_deployment_type"): - saml_deployment_type = StringHelper.toLowerCase(configurationAttributes.get("saml_deployment_type").getValue2()) - - if StringHelper.equalsIgnoreCase(saml_deployment_type, "map"): - saml_map_user = True - - if StringHelper.equalsIgnoreCase(saml_deployment_type, "enroll"): - saml_enroll_user = True - - if StringHelper.equalsIgnoreCase(saml_deployment_type, "enroll_all_attr"): - saml_enroll_all_user_attr = True - - saml_allow_basic_login = False - if configurationAttributes.containsKey("saml_allow_basic_login"): - saml_allow_basic_login = StringHelper.toBoolean(configurationAttributes.get("saml_allow_basic_login").getValue2(), False) - - use_basic_auth = False - if saml_allow_basic_login: - # Detect if user used basic authnetication method - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - if StringHelper.isNotEmpty(user_name) and StringHelper.isNotEmpty(user_password): - use_basic_auth = True - - if (step == 1) and saml_allow_basic_login and use_basic_auth: - print "Asimba. Authenticate for step 1. Basic authentication" - - identity.setWorkingParameter("saml_count_login_steps", 1) - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - logged_in = authenticationService.authenticate(user_name, user_password) - - if (not logged_in): - return False - - return True - - if (step == 1): - print "Asimba. Authenticate for step 1" - - currentSamlConfiguration = self.getCurrentSamlConfiguration(self.samlConfiguration, configurationAttributes, requestParameters) - if (currentSamlConfiguration == None): - print "Asimba. Prepare for step 1. Client saml configuration is invalid" - return False - - saml_response_array = requestParameters.get("SAMLResponse") - if ArrayHelper.isEmpty(saml_response_array): - print "Asimba. Authenticate for step 1. saml_response is empty" - return False - - saml_response = saml_response_array[0] - - print "Asimba. Authenticate for step 1. saml_response: '%s'" % saml_response - - samlResponse = Response(currentSamlConfiguration) - samlResponse.loadXmlFromBase64(saml_response) - - saml_validate_response = True - if configurationAttributes.containsKey("saml_validate_response"): - saml_validate_response = StringHelper.toBoolean(configurationAttributes.get("saml_validate_response").getValue2(), False) - - if saml_validate_response: - if not samlResponse.isValid(): - print "Asimba. Authenticate for step 1. saml_response isn't valid" - return False - - if samlResponse.isAuthnFailed(): - print "Asimba. Authenticate for step 1. saml_response AuthnFailed" - return False - - saml_response_attributes = samlResponse.getAttributes() - print "Asimba. Authenticate for step 1. attributes: '%s'" % saml_response_attributes - - if saml_map_user: - saml_user_uid = self.getSamlNameId(samlResponse) - if saml_user_uid == None: - return False - - # Use mapping to local IDP user - print "Asimba. Authenticate for step 1. Attempting to find user by oxExternalUid: saml: '%s'" % saml_user_uid - - # Check if the is user with specified saml_user_uid - find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "saml:%s" % saml_user_uid) - - if find_user_by_uid == None: - print "Asimba. Authenticate for step 1. Failed to find user" - print "Asimba. Authenticate for step 1. Setting count steps to 2" - identity.setWorkingParameter("saml_count_login_steps", 2) - identity.setWorkingParameter("saml_user_uid", saml_user_uid) - return True - - found_user_name = find_user_by_uid.getUserId() - print "Asimba. Authenticate for step 1. found_user_name: '%s'" % found_user_name - - user_authenticated = authenticationService.authenticate(found_user_name) - if user_authenticated == False: - print "Asimba. Authenticate for step 1. Failed to authenticate user" - return False - - print "Asimba. Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("saml_count_login_steps", 1) - - post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) - print "Asimba. Authenticate for step 1. post_login_result: '%s'" % post_login_result - - return post_login_result - elif saml_enroll_user: - # Convert SAML response to user entry - newUser = self.getMappedUser(configurationAttributes, requestParameters, saml_response_attributes) - - saml_user_uid = self.getNameId(samlResponse, newUser) - if saml_user_uid == None: - return False - - self.setDefaultUid(newUser, saml_user_uid) - newUser.setAttribute("oxExternalUid", "saml:%s" % saml_user_uid) - - # Use auto enrollment to local IDP - print "Asimba. Authenticate for step 1. Attempting to find user by oxExternalUid: saml: '%s'" % saml_user_uid - - # Check if there is user with specified saml_user_uid - find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "saml:%s" % saml_user_uid) - if find_user_by_uid == None: - # Auto user enrollment - print "Asimba. Authenticate for step 1. There is no user in LDAP. Adding user to local LDAP" - - print "Asimba. Authenticate for step 1. Attempting to add user '%s' with next attributes: '%s'" % (saml_user_uid, newUser.getCustomAttributes()) - user_unique = self.checkUserUniqueness(newUser) - if not user_unique: - print "Asimba. Authenticate for step 1. Failed to add user: '%s'. User not unique" % newUser.getUserId() - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to enroll. User with same key attributes exist already") - facesMessages.setKeepMessages() - return False - - find_user_by_uid = userService.addUser(newUser, True) - print "Asimba. Authenticate for step 1. Added new user with UID: '%s'" % find_user_by_uid.getUserId() - else: - if self.updateUser: - print "Asimba. Authenticate for step 1. Attempting to update user '%s' with next attributes: '%s'" % (saml_user_uid, newUser.getCustomAttributes()) - find_user_by_uid.setCustomAttributes(newUser.getCustomAttributes()) - userService.updateUser(find_user_by_uid) - print "Asimba. Authenticate for step 1. Updated user with UID: '%s'" % saml_user_uid - - found_user_name = find_user_by_uid.getUserId() - print "Asimba. Authenticate for step 1. found_user_name: '%s'" % found_user_name - - user_authenticated = authenticationService.authenticate(found_user_name) - if user_authenticated == False: - print "Asimba. Authenticate for step 1. Failed to authenticate user: '%s'" % found_user_name - return False - - print "Asimba. Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("saml_count_login_steps", 1) - - post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) - print "Asimba. Authenticate for step 1. post_login_result: '%s'" % post_login_result - - return post_login_result - elif saml_enroll_all_user_attr: - # Convert SAML response to user entry - newUser = self.getMappedAllAttributesUser(saml_response_attributes) - - saml_user_uid = self.getNameId(samlResponse, newUser) - if saml_user_uid == None: - return False - - self.setDefaultUid(newUser, saml_user_uid) - newUser.setAttribute("oxExternalUid", "saml:%s" % saml_user_uid) - - print "Asimba. Authenticate for step 1. Attempting to find user by oxExternalUid: saml:%s" % saml_user_uid - - # Check if there is user with specified saml_user_uid - find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "saml:%s" % saml_user_uid) - if find_user_by_uid == None: - # Auto user enrollment - print "Asimba. Authenticate for step 1. There is no user in LDAP. Adding user to local LDAP" - - print "Asimba. Authenticate for step 1. Attempting to add user '%s' with next attributes: '%s'" % (saml_user_uid, newUser.getCustomAttributes()) - user_unique = self.checkUserUniqueness(newUser) - if not user_unique: - print "Asimba. Authenticate for step 1. Failed to add user: '%s'. User not unique" % newUser.getUserId() - facesMessages = CdiUtil.bean(FacesMessages) - facesMessages.add(FacesMessage.SEVERITY_ERROR, "Failed to enroll. User with same key attributes exist already") - facesMessages.setKeepMessages() - return False - - find_user_by_uid = userService.addUser(newUser, True) - print "Asimba. Authenticate for step 1. Added new user with UID: '%s'" % find_user_by_uid.getUserId() - else: - if self.updateUser: - print "Asimba. Authenticate for step 1. Attempting to update user '%s' with next attributes: '%s'" % (saml_user_uid, newUser.getCustomAttributes()) - find_user_by_uid.setCustomAttributes(newUser.getCustomAttributes()) - userService.updateUser(find_user_by_uid) - print "Asimba. Authenticate for step 1. Updated user with UID: '%s'" % saml_user_uid - - found_user_name = find_user_by_uid.getUserId() - print "Asimba. Authenticate for step 1. found_user_name: '%s'" % found_user_name - - user_authenticated = authenticationService.authenticate(found_user_name) - if user_authenticated == False: - print "Asimba. Authenticate for step 1. Failed to authenticate user" - return False - - print "Asimba. Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("saml_count_login_steps", 1) - - post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) - print "Asimba. Authenticate for step 1. post_login_result: '%s'" % post_login_result - - return post_login_result - else: - if saml_user_uid == None: - return False - - # Check if the is user with specified saml_user_uid - print "Asimba. Authenticate for step 1. Attempting to find user by uid: '%s'" % saml_user_uid - - find_user_by_uid = userService.getUser(saml_user_uid) - if find_user_by_uid == None: - print "Asimba. Authenticate for step 1. Failed to find user" - return False - - found_user_name = find_user_by_uid.getUserId() - print "Asimba. Authenticate for step 1. found_user_name: '%s'" % found_user_name - - user_authenticated = authenticationService.authenticate(found_user_name) - if user_authenticated == False: - print "Asimba. Authenticate for step 1. Failed to authenticate user" - return False - - print "Asimba. Authenticate for step 1. Setting count steps to 1" - identity.setWorkingParameter("saml_count_login_steps", 1) - - post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) - print "Asimba. Authenticate for step 1. post_login_result: '%s'" % post_login_result - - return post_login_result - elif (step == 2): - print "Asimba. Authenticate for step 2" - - sessionAttributes = identity.getSessionId().getSessionAttributes() - if (sessionAttributes == None) or not sessionAttributes.containsKey("saml_user_uid"): - print "Asimba. Authenticate for step 2. saml_user_uid is empty" - return False - - saml_user_uid = sessionAttributes.get("saml_user_uid") - passed_step1 = StringHelper.isNotEmptyString(saml_user_uid) - if not passed_step1: - return False - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - logged_in = authenticationService.authenticate(user_name, user_password) - - if not logged_in: - return False - - # Check if there is user which has saml_user_uid - # Avoid mapping Saml account to more than one IDP account - find_user_by_uid = userService.getUserByAttribute("oxExternalUid", "saml:%s" % saml_user_uid) - - if find_user_by_uid == None: - # Add saml_user_uid to user one id UIDs - find_user_by_uid = userService.addUserAttribute(user_name, "oxExternalUid", "saml:%s" % saml_user_uid) - if find_user_by_uid == None: - print "Asimba. Authenticate for step 2. Failed to update current user" - return False - - post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) - print "Asimba. Authenticate for step 2. post_login_result: '%s'" % post_login_result - - return post_login_result - else: - found_user_name = find_user_by_uid.getUserId() - print "Asimba. Authenticate for step 2. found_user_name: '%s'" % found_user_name - - if StringHelper.equals(user_name, found_user_name): - post_login_result = self.samlExtensionPostLogin(configurationAttributes, find_user_by_uid) - print "Asimba. Authenticate for step 2. post_login_result: '%s'" % post_login_result - - return post_login_result - - return False - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - if (step == 1): - print "Asimba. Prepare for step 1" - - httpService = CdiUtil.bean(HttpService) - facesContext = CdiUtil.bean(FacesContext) - request = facesContext.getExternalContext().getRequest() - assertionConsumerServiceUrl = httpService.constructServerUrl(request) + "/postlogin.htm" - print "Asimba. Prepare for step 1. Prepared assertionConsumerServiceUrl: '%s'" % assertionConsumerServiceUrl - - currentSamlConfiguration = self.getCurrentSamlConfiguration(self.samlConfiguration, configurationAttributes, requestParameters) - if currentSamlConfiguration == None: - print "Asimba. Prepare for step 1. Client saml configuration is invalid" - return False - - # Generate an AuthRequest and send it to the identity provider - samlAuthRequest = AuthRequest(currentSamlConfiguration) - external_auth_request_uri = currentSamlConfiguration.getIdpSsoTargetUrl() + "?SAMLRequest=" + samlAuthRequest.getRequest(True, assertionConsumerServiceUrl) - - print "Asimba. Prepare for step 1. external_auth_request_uri: '%s'" % external_auth_request_uri - facesService = CdiUtil.bean(FacesService) - facesService.redirectToExternalURL(external_auth_request_uri) - - return True - elif (step == 2): - print "Asimba. Prepare for step 2" - - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - if (step == 2): - return Arrays.asList("saml_user_uid") - - return None - - def getCountAuthenticationSteps(self, configurationAttributes): - identity = CdiUtil.bean(Identity) - if identity.isSetWorkingParameter("saml_count_login_steps"): - return identity.getWorkingParameter("saml_count_login_steps") - - return 2 - - def getPageForStep(self, configurationAttributes, step): - if (step == 1): - saml_allow_basic_login = False - if configurationAttributes.containsKey("saml_allow_basic_login"): - saml_allow_basic_login = StringHelper.toBoolean(configurationAttributes.get("saml_allow_basic_login").getValue2(), False) - - if saml_allow_basic_login: - return "/login.xhtml" - else: - return "/auth/saml/samllogin.xhtml" - - return "/auth/saml/samlpostlogin.xhtml" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - - def isPassedStep1(): - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - user_name = credentials.getUsername() - passed_step1 = StringHelper.isNotEmptyString(user_name) - - return passed_step1 - - def loadCeritificate(self, asimba_saml_certificate_file): - asimba_saml_certificate = None - - # Load certificate from file - f = open(asimba_saml_certificate_file, 'r') - try: - asimba_saml_certificate = f.read() - except: - print "Asimba. Failed to load certificate from file: '%s'" % asimba_saml_certificate_file - return None - finally: - f.close() - - return asimba_saml_certificate - - def getClientConfiguration(self, configurationAttributes, requestParameters): - # Get client configuration - if configurationAttributes.containsKey("saml_client_configuration_attribute"): - saml_client_configuration_attribute = configurationAttributes.get("saml_client_configuration_attribute").getValue2() - print "Asimba. GetClientConfiguration. Using client attribute: '%s'" % saml_client_configuration_attribute - - if requestParameters == None: - return None - - client_id = None - client_id_array = requestParameters.get("client_id") - if ArrayHelper.isNotEmpty(client_id_array) and StringHelper.isNotEmptyString(client_id_array[0]): - client_id = client_id_array[0] - - if client_id == None: - identity = CdiUtil.bean(Identity) - if identity.getSessionId() != None: - client_id = identity.getSessionId().getSessionAttributes().get("client_id") - - if client_id == None: - print "Asimba. GetClientConfiguration. client_id is empty" - return None - - clientService = CdiUtil.bean(ClientService) - client = clientService.getClient(client_id) - if client == None: - print "Asimba. GetClientConfiguration. Failed to find client '%s' in local LDAP" % client_id - return None - - saml_client_configuration = clientService.getCustomAttribute(client, saml_client_configuration_attribute) - if (saml_client_configuration == None) or StringHelper.isEmpty(saml_client_configuration.getValue()): - print "Asimba. GetClientConfiguration. Client '%s' attribute '%s' is empty" % ( client_id, saml_client_configuration_attribute ) - else: - print "Asimba. GetClientConfiguration. Client '%s' attribute '%s' is '%s'" % ( client_id, saml_client_configuration_attribute, saml_client_configuration ) - return saml_client_configuration - - return None - - def getCurrentSamlConfiguration(self, currentSamlConfiguration, configurationAttributes, requestParameters): - saml_client_configuration = self.getClientConfiguration(configurationAttributes, requestParameters) - if saml_client_configuration == None: - return currentSamlConfiguration - - saml_client_configuration_value = json.loads(saml_client_configuration.getValue()) - - client_asimba_saml_certificate = None - client_asimba_saml_certificate_file = saml_client_configuration_value["asimba_saml_certificate_file"] - if StringHelper.isNotEmpty(client_asimba_saml_certificate_file): - client_asimba_saml_certificate = self.loadCeritificate(client_asimba_saml_certificate_file) - if StringHelper.isEmpty(client_asimba_saml_certificate): - print "Asimba. BuildClientSamlConfiguration. File with x509 certificate should be not empty. Using default configuration" - return currentSamlConfiguration - - clientSamlConfiguration = currentSamlConfiguration.clone() - - if client_asimba_saml_certificate != None: - clientSamlConfiguration.loadCertificateFromString(client_asimba_saml_certificate) - - client_asimba_entity_id = saml_client_configuration_value["asimba_entity_id"] - clientSamlConfiguration.setIssuer(client_asimba_entity_id) - - saml_use_authn_context = saml_client_configuration_value["saml_use_authn_context"] - client_use_saml_use_authn_context = StringHelper.toBoolean(saml_use_authn_context, True) - clientSamlConfiguration.setUseRequestedAuthnContext(client_use_saml_use_authn_context) - - return clientSamlConfiguration - - def prepareAttributesMapping(self, saml_idp_attributes_mapping): - saml_idp_attributes_mapping_json = json.loads(saml_idp_attributes_mapping) - - if len(saml_idp_attributes_mapping_json) == 0: - print "Asimba. PrepareAttributesMapping. There is no attributes mapping specified in saml_idp_attributes_mapping property" - return None - - attributeMapping = IdentityHashMap() - for local_attribute_name in saml_idp_attributes_mapping_json: - localAttribute = StringHelper.toLowerCase(local_attribute_name) - for idp_attribute_name in saml_idp_attributes_mapping_json[local_attribute_name]: - idpAttribute = StringHelper.toLowerCase(idp_attribute_name) - attributeMapping.put(idpAttribute, localAttribute) - - return attributeMapping - - def prepareUserObjectClasses(self, configurationAttributes): - user_object_classes = configurationAttributes.get("user_object_classes").getValue2() - - user_object_classes_list_array = StringHelper.split(user_object_classes, ",") - if ArrayHelper.isEmpty(user_object_classes_list_array): - return None - - return user_object_classes_list_array - - def prepareUserEnforceUniquenessAttributes(self, configurationAttributes): - enforce_uniqueness_attr_list = configurationAttributes.get("enforce_uniqueness_attr_list").getValue2() - - enforce_uniqueness_attr_list_array = StringHelper.split(enforce_uniqueness_attr_list, ",") - if ArrayHelper.isEmpty(enforce_uniqueness_attr_list_array): - return None - - return enforce_uniqueness_attr_list_array - - def prepareCurrentAttributesMapping(self, currentAttributesMapping, configurationAttributes, requestParameters): - saml_client_configuration = self.getClientConfiguration(configurationAttributes, requestParameters) - if saml_client_configuration == None: - return currentAttributesMapping - - saml_client_configuration_value = json.loads(saml_client_configuration.getValue()) - - clientAttributesMapping = self.prepareAttributesMapping(saml_client_configuration_value["saml_idp_attributes_mapping"]) - if clientAttributesMapping == None: - print "Asimba. PrepareCurrentAttributesMapping. Client attributes mapping is invalid. Using default one" - return currentAttributesMapping - - return clientAttributesMapping - - def samlExtensionPostLogin(self, configurationAttributes, user): - if self.samlExtensionModule == None: - return True - try: - post_login_result = self.samlExtensionModule.postLogin(configurationAttributes, user) - print "Asimba. ExtensionPostlogin result: '%s'" % post_login_result - - return post_login_result - except Exception, ex: - print "Asimba. ExtensionPostlogin. Failed to execute postLogin method" - print "Asimba. ExtensionPostlogin. Unexpected error:", ex - return False - except java.lang.Throwable, ex: - print "Asimba. ExtensionPostlogin. Failed to execute postLogin method" - ex.printStackTrace() - return False - - def checkUserUniqueness(self, user): - if self.userEnforceAttributesUniqueness == None: - return True - - userService = CdiUtil.bean(UserService) - - # Prepare user object to search by pattern - userBaseDn = userService.getDnForUser(None) - - userToSearch = User() - userToSearch.setDn(userBaseDn) - - for userAttributeName in self.userEnforceAttributesUniqueness: - attribute_values_list = user.getAttributeValues(userAttributeName) - if (attribute_values_list != None) and (attribute_values_list.size() > 0): - userToSearch.setAttribute(userAttributeName, attribute_values_list) - - users = userService.getUsersBySample(userToSearch, 1) - if users.size() > 0: - return False - - return True - - def getMappedUser(self, configurationAttributes, requestParameters, saml_response_attributes): - # Convert Saml result attributes keys to lover case - saml_response_normalized_attributes = HashMap() - for saml_response_attribute_entry in saml_response_attributes.entrySet(): - saml_response_normalized_attributes.put(StringHelper.toLowerCase(saml_response_attribute_entry.getKey()), saml_response_attribute_entry.getValue()) - - currentAttributesMapping = self.prepareCurrentAttributesMapping(self.attributesMapping, configurationAttributes, requestParameters) - print "Asimba. Get mapped user. Using next attributes mapping '%s'" % currentAttributesMapping - - newUser = User() - - # Set custom object classes - if self.userObjectClasses != None: - print "Asimba. Get mapped user. User custom objectClasses to add persons: '%s'" % Util.array2ArrayList(self.userObjectClasses) - newUser.setCustomObjectClasses(self.userObjectClasses) - - for attributesMappingEntry in currentAttributesMapping.entrySet(): - idpAttribute = attributesMappingEntry.getKey() - localAttribute = attributesMappingEntry.getValue() - - if self.debugEnrollment: - print "Asimba. Get mapped user. Trying to map '%s' into '%s'" % (idpAttribute, localAttribute) - - localAttributeValue = saml_response_normalized_attributes.get(idpAttribute) - if localAttributeValue != None: - if self.debugEnrollment: - print "Asimba. Get mapped user. Setting attribute '%s' value '%s'" % (localAttribute, localAttributeValue) - newUser.setAttribute(localAttribute, localAttributeValue) - else: - if newUser.getAttribute(localAttribute) == None: - newUser.setAttribute(localAttribute, ArrayList()) - - return newUser - - def getMappedAllAttributesUser(self, saml_response_attributes): - user = User() - - # Set custom object classes - if self.userObjectClasses != None: - print "Asimba. Get mapped all attributes user. User custom objectClasses to add persons: '%s'" % Util.array2ArrayList(self.userObjectClasses) - user.setCustomObjectClasses(self.userObjectClasses) - - # Prepare map to do quick mapping - attributeService = CdiUtil.bean(AttributeService) - ldapAttributes = attributeService.getAllAttributes() - samlUriToAttributesMap = HashMap() - for ldapAttribute in ldapAttributes: - saml2Uri = ldapAttribute.getSaml2Uri() - if saml2Uri == None: - saml2Uri = attributeService.getDefaultSaml2Uri(ldapAttribute.getName()) - samlUriToAttributesMap.put(saml2Uri, ldapAttribute.getName()) - - customAttributes = ArrayList() - for key in saml_response_attributes.keySet(): - ldapAttributeName = samlUriToAttributesMap.get(key) - if ldapAttributeName == None: - print "Asimba. Get mapped all attributes user. Skipping saml attribute: '%s'" % key - continue - - if StringHelper.equalsIgnoreCase(ldapAttributeName, "uid"): - continue - - attribute = CustomAttribute(ldapAttributeName) - attribute.setValues(saml_response_attributes.get(key)) - customAttributes.add(attribute) - - user.setCustomAttributes(customAttributes) - - return user - - def getNameId(self, samlResponse, newUser): - if self.generateNameId: - saml_user_uid = self.generateNameUid(newUser) - else: - saml_user_uid = self.getSamlNameId(samlResponse) - - return saml_user_uid - - def getSamlNameId(self, samlResponse): - saml_response_name_id = samlResponse.getNameId() - if StringHelper.isEmpty(saml_response_name_id): - print "Asimba. Get Saml response. saml_response_name_id is invalid" - return None - - print "Asimba. Get Saml response. saml_response_name_id: '%s'" % saml_response_name_id - - # Use persistent Id as saml_user_uid - return saml_response_name_id - - def generateNameUid(self, user): - if self.userEnforceAttributesUniqueness == None: - print "Asimba. Build local external uid. User enforce attributes uniqueness not specified" - return None - - sb = StringBuilder() - first = True - for userAttributeName in self.userEnforceAttributesUniqueness: - if not first: - sb.append("!") - first = False - attribute_values_list = user.getAttributeValues(userAttributeName) - if (attribute_values_list != None) and (attribute_values_list.size() > 0): - first_attribute_value = attribute_values_list.get(0) - sb.append(first_attribute_value) - - return sb.toString() - - def setDefaultUid(self, user, saml_user_uid): - if StringHelper.isEmpty(user.getUserId()): - user.setUserId(saml_user_uid) diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar deleted file mode 100644 index 0af9d618a8e..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar.md5 b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar.md5 deleted file mode 100644 index 46552dca80c..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -a68c1030a94d67cbc64a12f4f760e82c \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar.sha1 b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar.sha1 deleted file mode 100644 index 431ae018f5c..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -578751f9da59d25403805867930db7ed458c3ae4 \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom deleted file mode 100644 index fd0477f43ac..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom +++ /dev/null @@ -1,8 +0,0 @@ - - - 4.0.0 - com.google.gcm - gcm-server - 1.0.1.gluu - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom.md5 b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom.md5 deleted file mode 100644 index 6126b5f4080..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom.md5 +++ /dev/null @@ -1 +0,0 @@ -3e2f5fe7273ec568da5d8daab6cb99a3 \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom.sha1 b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom.sha1 deleted file mode 100644 index eb0541fd960..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/1.0.1.gluu/gcm-server-1.0.1.gluu.pom.sha1 +++ /dev/null @@ -1 +0,0 @@ -82419a7d510b6809d6e34dcf84b12fccd3d63ab1 \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml deleted file mode 100644 index 3fe315a7a2a..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - com.google.gcm - gcm-server - - 1.0.1.gluu - - 1.0.1.gluu - - 20160713194346 - - diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml.md5 b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml.md5 deleted file mode 100644 index bd2630a92ec..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml.md5 +++ /dev/null @@ -1 +0,0 @@ -6ed9b8a162275e13f176b718271fabac \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml.sha1 b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml.sha1 deleted file mode 100644 index 4083cf36c54..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/repository/com/google/gcm/gcm-server/maven-metadata.xml.sha1 +++ /dev/null @@ -1 +0,0 @@ -2c9a252aa4d788e7702cac5dafb31e0dd6393acf \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/sample/super_gluu_creds.json b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/sample/super_gluu_creds.json deleted file mode 100644 index b42f5a6b5ef..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/super_gluu/sample/super_gluu_creds.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "android":{ - "gcm":{ - "enabled":false, - "api_key":"" - }, - "sns":{ - "enabled":false, - "platform_arn":"arn:aws:sns:..." - }, - "gluu":{ - "enabled":true, - "access_key":"36WH2JiexBOoAIBP", - "secret_access_key":"ueqsU2Dc7m3r4HmLz4M79DpzzCNqTfek" - } - }, - "ios":{ - "apns":{ - "enabled":false, - "p12_file_path":"/etc/certs/SuperGluu-NotificationCertificate.p12", - "p12_password":"password", - "production":false - }, - "sns":{ - "enabled":false, - "platform_arn":"arn:aws:sns:...", - "production":false - }, - "gluu":{ - "enabled":true, - "access_key":"auONAdePWoYFBX6V", - "secret_access_key":"f050aW0nnihym0GwktWd7O15jGSQcoei" - } - }, - "sns":{ - "access_key":"", - "secret_key":"", - "region":"" - }, - "gluu":{ - "server_uri":"https://api.gluu.org" - } -} diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/toopher/tpauthenticate.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/toopher/tpauthenticate.xhtml deleted file mode 100644 index 2b97893b950..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/toopher/tpauthenticate.xhtml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - #{msgs['toopher.pageTitle']} - - -
- - - -
-
-
\ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/toopher/tppair.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/toopher/tppair.xhtml deleted file mode 100644 index a28ce1a08be..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/toopher/tppair.xhtml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - oxAuth Toopher - Login - - -
- - - -
-
-
\ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/UafExternalAuthenticator.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/UafExternalAuthenticator.py deleted file mode 100644 index 7fcb634d9a1..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/UafExternalAuthenticator.py +++ /dev/null @@ -1,398 +0,0 @@ -# Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. -# Copyright (c) 2020, Janssen Project -# -# Author: Yuriy Movchan -# - -# Requires the following custom properties and values: -# uaf_server_uri: -# -# These are non mandatory custom properties and values: -# uaf_policy_name: default -# send_push_notifaction: false -# registration_uri: https:///identity/register -# qr_options: { width: 400, height: 400 } - -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from io.jans.as.server.service import AuthenticationService, SessionIdService -from io.jans.as.server.service.common import UserService -from io.jans.util import StringHelper, ArrayHelper -from io.jans.as.server.util import ServerUtil -from org.gluu.oxauth.model.config import Constants -from jakarta.ws.rs.core import Response -from java.util import Arrays -from io.jans.as.server.service.net import HttpService -from org.apache.http.params import CoreConnectionPNames - -import sys -import java -import json - -class PersonAuthentication(PersonAuthenticationType): - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - - def init(self, customScript, configurationAttributes): - print "UAF. Initialization" - - if not configurationAttributes.containsKey("uaf_server_uri"): - print "UAF. Initialization. Property uaf_server_uri is mandatory" - return False - - self.uaf_server_uri = configurationAttributes.get("uaf_server_uri").getValue2() - - self.uaf_policy_name = "default" - if configurationAttributes.containsKey("uaf_policy_name"): - self.uaf_policy_name = configurationAttributes.get("uaf_policy_name").getValue2() - - self.send_push_notifaction = False - if configurationAttributes.containsKey("send_push_notifaction"): - self.send_push_notifaction = StringHelper.toBoolean(configurationAttributes.get("send_push_notifaction").getValue2(), False) - - self.registration_uri = None - if configurationAttributes.containsKey("registration_uri"): - self.registration_uri = configurationAttributes.get("registration_uri").getValue2() - - self.customQrOptions = {} - if configurationAttributes.containsKey("qr_options"): - self.customQrOptions = configurationAttributes.get("qr_options").getValue2() - - print "UAF. Initializing HTTP client" - httpService = CdiUtil.bean(HttpService) - self.http_client = httpService.getHttpsClient() - http_client_params = self.http_client.getParams() - http_client_params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 15 * 1000) - - print "UAF. Initialized successfully. uaf_server_uri: '%s', uaf_policy_name: '%s', send_push_notifaction: '%s', registration_uri: '%s', qr_options: '%s'" % (self.uaf_server_uri, self.uaf_policy_name, self.send_push_notifaction, self.registration_uri, self.customQrOptions) - - print "UAF. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "UAF. Destroy" - print "UAF. Destroyed successfully" - return True - - def getApiVersion(self): - return 11 - - def getAuthenticationMethodClaims(self, requestParameters): - return None - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def authenticate(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - session_attributes = identity.getSessionId().getSessionAttributes() - - self.setRequestScopedParameters(identity) - - if (step == 1): - print "UAF. Authenticate for step 1" - - user_name = credentials.getUsername() - - authenticated_user = self.processBasicAuthentication(credentials) - if authenticated_user == None: - return False - - uaf_auth_method = "authenticate" - # Uncomment this block if you need to allow user second device registration - #enrollment_mode = ServerUtil.getFirstValue(requestParameters, "loginForm:registerButton") - #if StringHelper.isNotEmpty(enrollment_mode): - # uaf_auth_method = "enroll" - - if uaf_auth_method == "authenticate": - user_enrollments = self.findEnrollments(credentials) - if len(user_enrollments) == 0: - uaf_auth_method = "enroll" - print "UAF. Authenticate for step 1. There is no UAF enrollment for user '%s'. Changing uaf_auth_method to '%s'" % (user_name, uaf_auth_method) - - print "UAF. Authenticate for step 1. uaf_auth_method: '%s'" % uaf_auth_method - - identity.setWorkingParameter("uaf_auth_method", uaf_auth_method) - - return True - elif (step == 2): - print "UAF. Authenticate for step 2" - - session = CdiUtil.bean(SessionIdService).getSessionId() - if session == None: - print "UAF. Prepare for step 2. Failed to determine session_id" - return False - - user = authenticationService.getAuthenticatedUser() - if (user == None): - print "UAF. Authenticate for step 2. Failed to determine user name" - return False - user_name = user.getUserId() - - uaf_auth_result = ServerUtil.getFirstValue(requestParameters, "auth_result") - if uaf_auth_result != "success": - print "UAF. Authenticate for step 2. auth_result is '%s'" % uaf_auth_result - return False - - # Restore state from session - uaf_auth_method = session_attributes.get("uaf_auth_method") - - if not uaf_auth_method in ['enroll', 'authenticate']: - print "UAF. Authenticate for step 2. Failed to authenticate user. uaf_auth_method: '%s'" % uaf_auth_method - return False - - # Request STATUS_OBB - if True: - #TODO: Remove this condition - # It's workaround becuase it's not possible to call STATUS_OBB 2 times. First time on browser and second ime on server - uaf_user_device_handle = ServerUtil.getFirstValue(requestParameters, "auth_handle") - else: - uaf_obb_auth_method = session_attributes.get("uaf_obb_auth_method") - uaf_obb_server_uri = session_attributes.get("uaf_obb_server_uri") - uaf_obb_start_response = session_attributes.get("uaf_obb_start_response") - - # Prepare STATUS_OBB - uaf_obb_start_response_json = json.loads(uaf_obb_start_response) - uaf_obb_status_request_dictionary = { "operation": "STATUS_%s" % uaf_obb_auth_method, - "userName": user_name, - "needDetails": 1, - "oobStatusHandle": uaf_obb_start_response_json["oobStatusHandle"], - } - - uaf_obb_status_request = json.dumps(uaf_obb_status_request_dictionary, separators=(',',':')) - print "UAF. Authenticate for step 2. Prepared STATUS request: '%s' to send to '%s'" % (uaf_obb_status_request, uaf_obb_server_uri) - - uaf_status_obb_response = self.executePost(uaf_obb_server_uri, uaf_obb_status_request) - if uaf_status_obb_response == None: - return False - - print "UAF. Authenticate for step 2. Get STATUS response: '%s'" % uaf_status_obb_response - uaf_status_obb_response_json = json.loads(uaf_status_obb_response) - - if uaf_status_obb_response_json["statusCode"] != 4000: - print "UAF. Authenticate for step 2. UAF operation status is invalid. statusCode: '%s'" % uaf_status_obb_response_json["statusCode"] - return False - - uaf_user_device_handle = uaf_status_obb_response_json["additionalInfo"]["authenticatorsResult"]["handle"] - - if StringHelper.isEmpty(uaf_user_device_handle): - print "UAF. Prepare for step 2. Failed to get UAF handle" - return False - - uaf_user_external_uid = "uaf:%s" % uaf_user_device_handle - print "UAF. Authenticate for step 2. UAF handle: '%s'" % uaf_user_external_uid - - if uaf_auth_method == "authenticate": - # Validate if user used device with same keYHandle - user_enrollments = self.findEnrollments(credentials) - if len(user_enrollments) == 0: - uaf_auth_method = "enroll" - print "UAF. Authenticate for step 2. There is no UAF enrollment for user '%s'." % user_name - return False - - for user_enrollment in user_enrollments: - if StringHelper.equalsIgnoreCase(user_enrollment, uaf_user_device_handle): - print "UAF. Authenticate for step 2. There is UAF enrollment for user '%s'. User authenticated successfully" % user_name - return True - else: - userService = CdiUtil.bean(UserService) - - # Double check just to make sure. We did checking in previous step - # Check if there is user which has uaf_user_external_uid - # Avoid mapping user cert to more than one IDP account - find_user_by_external_uid = userService.getUserByAttribute("oxExternalUid", uaf_user_external_uid) - if find_user_by_external_uid == None: - # Add uaf_user_external_uid to user's external GUID list - find_user_by_external_uid = userService.addUserAttribute(user_name, "oxExternalUid", uaf_user_external_uid) - if find_user_by_external_uid == None: - print "UAF. Authenticate for step 2. Failed to update current user" - return False - - return True - - return False - else: - return False - - def prepareForStep(self, configurationAttributes, requestParameters, step): - authenticationService = CdiUtil.bean(AuthenticationService) - - identity = CdiUtil.bean(Identity) - credentials = identity.getCredentials() - - session_attributes = identity.getSessionId().getSessionAttributes() - - self.setRequestScopedParameters(identity) - - if (step == 1): - return True - elif (step == 2): - print "UAF. Prepare for step 2" - - session = CdiUtil.bean(SessionIdService).getSessionId() - if session == None: - print "UAF. Prepare for step 2. Failed to determine session_id" - return False - - user = authenticationService.getAuthenticatedUser() - if (user == None): - print "UAF. Prepare for step 2. Failed to determine user name" - return False - - uaf_auth_method = session_attributes.get("uaf_auth_method") - if StringHelper.isEmpty(uaf_auth_method): - print "UAF. Prepare for step 2. Failed to determine auth_method" - return False - - print "UAF. Prepare for step 2. uaf_auth_method: '%s'" % uaf_auth_method - - uaf_obb_auth_method = "OOB_REG" - uaf_obb_server_uri = self.uaf_server_uri + "/nnl/v2/reg" - if StringHelper.equalsIgnoreCase(uaf_auth_method, "authenticate"): - uaf_obb_auth_method = "OOB_AUTH" - uaf_obb_server_uri = self.uaf_server_uri + "/nnl/v2/auth" - - # Prepare START_OBB - uaf_obb_start_request_dictionary = { "operation": "START_%s" % uaf_obb_auth_method, - "userName": user.getUserId(), - "policyName": "default", - "oobMode": - { "qr": "true", "rawData": "false", "push": "false" } - } - - uaf_obb_start_request = json.dumps(uaf_obb_start_request_dictionary, separators=(',',':')) - print "UAF. Prepare for step 2. Prepared START request: '%s' to send to '%s'" % (uaf_obb_start_request, uaf_obb_server_uri) - - # Request START_OBB - uaf_obb_start_response = self.executePost(uaf_obb_server_uri, uaf_obb_start_request) - if uaf_obb_start_response == None: - return False - - print "UAF. Prepare for step 2. Get START response: '%s'" % uaf_obb_start_response - uaf_obb_start_response_json = json.loads(uaf_obb_start_response) - - # Prepare STATUS_OBB - #TODO: Remove needDetails parameter - uaf_obb_status_request_dictionary = { "operation": "STATUS_%s" % uaf_obb_auth_method, - "userName": user.getUserId(), - "needDetails": 1, - "oobStatusHandle": uaf_obb_start_response_json["oobStatusHandle"], - } - - uaf_obb_status_request = json.dumps(uaf_obb_status_request_dictionary, separators=(',',':')) - print "UAF. Prepare for step 2. Prepared STATUS request: '%s' to send to '%s'" % (uaf_obb_status_request, uaf_obb_server_uri) - - identity.setWorkingParameter("uaf_obb_auth_method", uaf_obb_auth_method) - identity.setWorkingParameter("uaf_obb_server_uri", uaf_obb_server_uri) - identity.setWorkingParameter("uaf_obb_start_response", uaf_obb_start_response) - identity.setWorkingParameter("qr_image", uaf_obb_start_response_json["modeResult"]["qrCode"]["qrImage"]) - identity.setWorkingParameter("uaf_obb_status_request", uaf_obb_status_request) - - return True - else: - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - return Arrays.asList("uaf_auth_method", "uaf_obb_auth_method", "uaf_obb_server_uri", "uaf_obb_start_response") - - def getCountAuthenticationSteps(self, configurationAttributes): - return 2 - - def getPageForStep(self, configurationAttributes, step): - if (step == 2): - return "/auth/uaf/login.xhtml" - - return "" - - def getNextStep(self, configurationAttributes, requestParameters, step): - return -1 - - def getLogoutExternalUrl(self, configurationAttributes, requestParameters): - print "Get external logout URL call" - return None - - def logout(self, configurationAttributes, requestParameters): - return True - - def setRequestScopedParameters(self, identity): - if self.registration_uri != None: - identity.setWorkingParameter("external_registration_uri", self.registration_uri) - identity.setWorkingParameter("qr_options", self.customQrOptions) - - def processBasicAuthentication(self, credentials): - userService = CdiUtil.bean(UserService) - authenticationService = CdiUtil.bean(AuthenticationService) - - user_name = credentials.getUsername() - user_password = credentials.getPassword() - - logged_in = False - if StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password): - logged_in = authenticationService.authenticate(user_name, user_password) - - if not logged_in: - return None - - find_user_by_uid = authenticationService.getAuthenticatedUser() - if find_user_by_uid == None: - print "UAF. Process basic authentication. Failed to find user '%s'" % user_name - return None - - return find_user_by_uid - - def findEnrollments(self, credentials): - result = [] - - userService = CdiUtil.bean(UserService) - user_name = credentials.getUsername() - user = userService.getUser(user_name, "oxExternalUid") - if user == None: - print "UAF. Find enrollments. Failed to find user" - return result - - user_custom_ext_attribute = userService.getCustomAttribute(user, "oxExternalUid") - if user_custom_ext_attribute == None: - return result - - uaf_prefix = "uaf:" - uaf_prefix_length = len(uaf_prefix) - for user_external_uid in user_custom_ext_attribute.getValues(): - index = user_external_uid.find(uaf_prefix) - if index != -1: - enrollment_uid = user_external_uid[uaf_prefix_length:] - result.append(enrollment_uid) - - return result - - def executePost(self, request_uri, request_data): - httpService = CdiUtil.bean(HttpService) - - request_headers = { "Content-type" : "application/json; charset=UTF-8", "Accept" : "application/json" } - - try: - http_service_response = httpService.executePost(self.http_client, request_uri, None, request_headers, request_data) - http_response = http_service_response.getHttpResponse() - except: - print "UAF. Validate POST response. Exception: ", sys.exc_info()[1] - return None - - try: - if not httpService.isResponseStastusCodeOk(http_response): - print "UAF. Validate POST response. Get invalid response from server: %s" % str(http_response.getStatusLine().getStatusCode()) - httpService.consume(http_response) - return None - - response_bytes = httpService.getResponseContent(http_response) - response_string = httpService.convertEntityToString(response_bytes) - httpService.consume(http_response) - - return response_string - finally: - http_service_response.closeConnection() - return None diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/gluu_uaf_integration_authentication_workflow.png b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/gluu_uaf_integration_authentication_workflow.png deleted file mode 100644 index c247c7641e7..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/gluu_uaf_integration_authentication_workflow.png and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/oob_qr_code.png b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/oob_qr_code.png deleted file mode 100644 index ce0716ef00c..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/oob_qr_code.png and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/typical_uaf_architecture.png b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/typical_uaf_architecture.png deleted file mode 100644 index 44fe121758c..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/typical_uaf_architecture.png and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/uaf_device_integration_models.png b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/uaf_device_integration_models.png deleted file mode 100644 index 02a32733377..00000000000 Binary files a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/img/uaf_device_integration_models.png and /dev/null differ diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/sequence_diagram.txt b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/sequence_diagram.txt deleted file mode 100644 index 0a557e3be67..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/uaf/sequence_diagram.txt +++ /dev/null @@ -1,25 +0,0 @@ -Title UAF authentication workflow - -Person->Browser: Open RP URL -Browser->RP: Protected resource -RP->Gluu Server: Start AuthZ & AuthN -Gluu Server->UAF Script: Start User/Password + UAF -UAF Script->UAF Script: 1) Verify user/password -UAF Script->Nok Nok Server: START_OOB -Nok Nok Server->UAF Script: QR code for mobile application -UAF Script->Browser: 2) Render UAF login page with QR code - -Person->UAF Mobile: Start UAF application -UAF Mobile->Browser: Scan QR code -UAF Mobile->Nok Nok Server: INIT_OBB -Person->UAF Mobile: Biometric authentication -UAF Mobile->Nok Nok Server: FINISH_OBB - -Browser->Nok Nok Server: STATUS_OBB with delay 5 seconds -Browser->UAF Script: 3) Send response -UAF Script->Nok Nok Server: STATUS_OBB -UAF Script->Nok Nok Server: CANCEL_OBB if UAF authentication failed - -RP->Gluu Server: Request authorization -RP->Gluu Server: Request tokens -RP->Gluu Server: Request user_info diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wikid/wikidlogin.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wikid/wikidlogin.xhtml deleted file mode 100644 index 22fa40fce63..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wikid/wikidlogin.xhtml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - #{msgs['wikid.pageTitle']} - - - - - - -
-
- - - - - -
-
- -
-
\ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wikid/wikidregister.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wikid/wikidregister.xhtml deleted file mode 100644 index 9a395184c45..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wikid/wikidregister.xhtml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - #{msgs['wikid.pageTitle']} - - - - - - -
-
- - - - - -
-
- -
-
\ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/README.md b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/README.md deleted file mode 100644 index 62b46b60745..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# WWPass integration for Gluu - -[WWPass](https://wwpass.com/) replaces the traditional username and password -login with a more advanced multi-factor authentication solution. WWPass employs -strong cryptography and robust combination of authentication factors to deliver -a secure and user-friendly authentication experience. WWPass authentication -starts with a smartphone app or a hardware token as the first authentication -factor. Then additional authentication factors such as PIN or biometrics can be -added to verify the user identity further. - -## Installation - -To install WWPass support in Gluu server refer to [INSTALLATION.md](INSTALLATION.md). - -To install additional components refer to main wwpass-gluu repository at https://github.com/wwpass/gluu - -## Contacts - -Feel free to contact WWPass at support@wwpass.com if you have trouble integrating WWPass in your Gluu setup \ No newline at end of file diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/checkemail.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/checkemail.xhtml deleted file mode 100644 index 59f10a80bc7..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/checkemail.xhtml +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
-
-
- - -

Enter a code that was sent to #{identity.getWorkingParameter('email')}

- - -

If you don't receive the email, check that the email address is associated with an active user account.

- - - -
-
-
-
-
- -
- -
- diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/wwpass.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/wwpass.xhtml deleted file mode 100644 index 8330f86c4b7..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/wwpass.xhtml +++ /dev/null @@ -1,285 +0,0 @@ - - - - - - - - - - - - - - - - - -
-
-

Scan the QR code

-

- with WWPassTMPassKeyApp tolog in -

-
- -
- - -
-

Download WWPassTMPassKeyApp from -

- AppStore - Google Play -
-
- - - -
- -
- diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/wwpassbind.xhtml b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/wwpassbind.xhtml deleted file mode 100644 index 2b93995aabc..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/pages/auth/wwpass/wwpassbind.xhtml +++ /dev/null @@ -1,329 +0,0 @@ - - - - - - - - - - - - - - - - - - - -
-
-
-

#{identity.getWorkingParameter('errors')}

-
- -
- -
- - -
- -
- -
- - -
- - -
- -
- - -
- - -
-
-
-
- -
-
- - - -
-
- -
-

You presented a new WWPass Key, not associated with any account. If you already have an account, and need to replace your WWPass Key, please follow this link.

-
-
-
-
- - - -
- -
- diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/static/js/wwpass-frontend.js b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/static/js/wwpass-frontend.js deleted file mode 100644 index aeb1d82d55a..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/static/js/wwpass-frontend.js +++ /dev/null @@ -1,6097 +0,0 @@ -(function () { - 'use strict'; - - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - - var classCallCheck = _classCallCheck; - - function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; - } - - var createClass = _createClass; - - function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } - - return obj; - } - - var defineProperty = _defineProperty; - - function _objectSpread(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - var ownKeys = Object.keys(Object(source)); - - if (typeof Object.getOwnPropertySymbols === 'function') { - ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { - return Object.getOwnPropertyDescriptor(source, sym).enumerable; - })); - } - - ownKeys.forEach(function (key) { - defineProperty(target, key, source[key]); - }); - } - - return target; - } - - var objectSpread = _objectSpread; - - /* Constants */ - - /* Status codes */ - var WWPASS_OK_MSG = 'OK'; - var WWPASS_STATUS = { - CONTINUE: 100, - OK: 200, - INTERNAL_ERROR: 400, - ALREADY_PERSONALIZED: 401, - PASSWORD_MISMATCH: 402, - PASSWORD_LOCKOUT: 403, - WRONG_KEY: 404, - WRONG_KEY_SECOND: 405, - NOT_A_KEY: 406, - NOT_A_KEY_SECOND: 407, - KEY_DISABLED: 408, - NOT_ALLOWED: 409, - BLANK_TOKEN: 410, - BLANK_SECOND_TOKEN: 411, - ACTIVITY_PROFILE_LOCKED: 412, - SSL_REQUIRED: 413, - BLANK_NORMAL_TOKEN: 414, - BLANK_SECOND_NORMAL_TOKEN: 415, - BLANK_MASTER_TOKEN: 416, - BLANK_SECOND_MASTER_TOKEN: 417, - NOT_ACTIVATED_TOKEN: 418, - NOT_ACTIVATED_SECOND_TOKEN: 419, - WRONG_KEY_SET: 420, - NO_VERIFIER: 421, - INCOMPLETE_KEYSET: 422, - INVALID_TICKET: 423, - SAME_TOKEN: 424, - NO_RECOVERY_INFO: 425, - BAD_RECOVERY_REQUEST: 426, - RECOVERY_FAILED: 427, - TERMINAL_ERROR: 500, - TERMINAL_NOT_FOUND: 501, - TERMINAL_BAD_REQUEST: 502, - NO_CONNECTION: 503, - NETWORK_ERROR: 504, - PROTOCOL_ERROR: 505, - UNKNOWN_HANDLER: 506, - TERMINAL_CANCELED: 590, - TIMEOUT: 600, - TICKET_TIMEOUT: 601, - USER_REJECT: 603, - NO_AUTH_INTERFACES_FOUND: 604, - TERMINAL_TIMEOUT: 605, - UNSUPPORTED_PLATFORM: 606 - }; - var WWPASS_NO_AUTH_INTERFACES_FOUND_MSG = 'No WWPass SecurityPack is found on your computer or WWPass Browser Plugin is disabled'; - var WWPASS_UNSUPPORTED_PLATFORM_MSG_TMPL = 'WWPass authentication is not supported on'; - var WWPASS_KEY_TYPE_PASSKEY = 'passkey'; - var WWPASS_KEY_TYPE_DEFAULT = WWPASS_KEY_TYPE_PASSKEY; - - var getCallbackURL = function getCallbackURL() { - var initialOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var defaultOptions = { - ppx: 'wwp_', - version: 2, - status: 200, - reason: 'OK', - ticket: undefined, - callbackURL: undefined, - hw: false // hardware legacy - - }; - - var options = objectSpread({}, defaultOptions, initialOptions); - - var url = ''; - - if (typeof options.callbackURL === 'string') { - url = options.callbackURL; - } - - var firstDelimiter = url.indexOf('?') === -1 ? '?' : '&'; - url += "".concat(firstDelimiter + encodeURIComponent(options.ppx), "version=").concat(options.version); - url += "&".concat(encodeURIComponent(options.ppx), "ticket=").concat(encodeURIComponent(options.ticket)); - url += "&".concat(encodeURIComponent(options.ppx), "status=").concat(encodeURIComponent(options.status)); - url += "&".concat(encodeURIComponent(options.ppx), "reason=").concat(encodeURIComponent(options.reason)); - - if (options.hw) { - url += "&".concat(encodeURIComponent(options.ppx), "hw=1"); - } - - return url; - }; - - var getUniversalURL = function getUniversalURL() { - var initialOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var allowCallbackURL = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - var defaultOptions = { - universal: false, - operation: 'auth', - ppx: 'wwp_', - version: 2, - ticket: undefined, - callbackURL: undefined, - clientKey: undefined - }; - - var options = objectSpread({}, defaultOptions, initialOptions); - - var url = options.universal ? 'https://get.wwpass.com/' : 'wwpass://'; - - if (options.operation === 'auth') { - url += 'auth'; - url += "?v=".concat(options.version); - url += "&t=".concat(encodeURIComponent(options.ticket)); - url += "&ppx=".concat(encodeURIComponent(options.ppx)); - - if (options.clientKey) { - url += "&ck=".concat(options.clientKey); - } - - if (options.callbackURL && allowCallbackURL) { - url += "&c=".concat(encodeURIComponent(options.callbackURL)); - } - } else { - url += "".concat(encodeURIComponent(options.operation), "?t=").concat(encodeURIComponent(options.ticket)); - } - - return url; - }; - - var navigateToCallback = function navigateToCallback(options) { - if (typeof options.callbackURL === 'function') { - options.callbackURL(getCallbackURL(options)); - } else { - // URL string - window.location.href = getCallbackURL(options); - } - }; - - var connectionPool = []; - - var closeConnectionPool = function closeConnectionPool() { - while (connectionPool.length) { - var connection = connectionPool.shift(); - - if (connection.readyState === WebSocket.OPEN) { - connection.close(); - } - } - }; - - var applyDefaults = function applyDefaults(initialOptions) { - var defaultOptions = { - ppx: 'wwp_', - version: 2, - ticket: undefined, - callbackURL: undefined, - returnErrors: false, - log: function log() {}, - development: false, - spfewsAddress: 'wss://spfews.wwpass.com', - echo: undefined, - clientKeyOnly: false - }; - return objectSpread({}, defaultOptions, initialOptions); - }; - /** - * WWPass SPFE WebSocket connection - * @param {object} options - * - * options = { - * 'ticket': undefined, // stirng - * 'callbackURL': undefined, //string - * 'development': false || 'string' , // work with another spfews.wwpass.* server - * 'log': function (message) || console.log, // another log handler - * 'echo': undefined - * } - */ - - - var getWebSocketResult = function getWebSocketResult(initialOptions) { - return new Promise(function (resolve, reject) { - var options = applyDefaults(initialOptions); - var clientKey = null; - var originalTicket = options.ticket; - var ttl = null; - - var settle = function settle(status, reason) { - if (status === 200) { - var result = { - ppx: options.ppx, - version: options.version, - status: status, - reason: WWPASS_OK_MSG, - ticket: options.ticket, - callbackURL: options.callbackURL, - clientKey: clientKey, - originalTicket: originalTicket, - ttl: ttl - }; - - if (!options.clientKeyOnly) { - navigateToCallback(result); - } - - resolve(result); - } else { - var err = { - ppx: options.ppx, - version: options.version, - status: status, - reason: reason, - ticket: options.ticket, - callbackURL: options.callbackURL - }; - - if ((status === WWPASS_STATUS.INTERNAL_ERROR || options.returnErrors) && !options.clientKeyOnly) { - navigateToCallback(err); - } - - reject(err); - } - }; - - if (!('WebSocket' in window)) { - settle(WWPASS_STATUS.INTERNAL_ERROR, 'WebSocket is not supported.'); - return; - } - - var websocketurl = options.spfewsAddress; - var socket = new WebSocket(websocketurl); - connectionPool.push(socket); - var log = options.log; - - socket.onopen = function () { - try { - log("Connected: ".concat(websocketurl)); - var message = JSON.stringify({ - ticket: options.ticket - }); - log("Sent message to server: ".concat(message)); - socket.send(message); - } catch (error) { - log(error); - settle(WWPASS_STATUS.INTERNAL_ERROR, 'WebSocket error'); - } - }; - - socket.onclose = function () { - try { - var index = connectionPool.indexOf(socket); - - if (index !== -1) { - connectionPool.splice(index, 1); - } - - log('Disconnected'); - resolve({ - refresh: true - }); - } catch (error) { - log(error); - settle(WWPASS_STATUS.INTERNAL_ERROR, 'WebSocket error'); - } - }; - - socket.onmessage = function (message) { - try { - log("Message received from server: ".concat(message.data)); - var response = JSON.parse(message.data); - var status = response.code; - var reason = response.reason; - - if ('clientKey' in response && !clientKey) { - clientKey = response.clientKey; - - if (response.originalTicket !== undefined) { - originalTicket = response.originalTicket; - ttl = response.ttl; - } - } - - if (status === 100) { - return; - } - - settle(status, reason); - socket.close(); - } catch (error) { - log(error); - settle(WWPASS_STATUS.INTERNAL_ERROR, 'WebSocket error'); - } - }; - }); - }; - - var abToB64 = function abToB64(data) { - return btoa(String.fromCharCode.apply(null, new Uint8Array(data))); - }; - - var b64ToAb = function b64ToAb(base64) { - var s = atob(base64); - var bytes = new Uint8Array(s.length); - - for (var i = 0; i < s.length; i += 1) { - bytes[i] = s.charCodeAt(i); - } - - return bytes.buffer; - }; - - var ab2str = function ab2str(buf) { - return String.fromCharCode.apply(null, new Uint16Array(buf)); - }; - - var str2ab = function str2ab(str) { - var buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char - - var bufView = new Uint16Array(buf); - - for (var i = 0, strLen = str.length; i < strLen; i += 1) { - bufView[i] = str.charCodeAt(i); - } - - return buf; - }; - - var crypto = window.crypto || window.msCrypto; - var subtle = crypto ? crypto.webkitSubtle || crypto.subtle : null; - - var encodeClientKey = function encodeClientKey(key) { - return abToB64(key).replace(/\+/g, '-').replace(/[/]/g, '.').replace(/=/g, '_'); - }; - - var encrypt = function encrypt(options, key, data) { - return subtle.encrypt(options, key, data); - }; - - var decrypt = function decrypt(options, key, data) { - return subtle.decrypt(options, key, data); - }; - - var importKey = function importKey(format, key, algoritm, extractable, operations) { - return subtle.importKey(format, key, algoritm, extractable, operations); - }; // eslint-disable-line max-len - - - var getRandomData = function getRandomData(buffer) { - return crypto.getRandomValues(buffer); - }; - - var concatBuffers = function concatBuffers() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - var totalLen = args.reduce(function (accumulator, curentAB) { - return accumulator + curentAB.byteLength; - }, 0); - var i = 0; - var result = new Uint8Array(totalLen); - - while (args.length > 0) { - result.set(new Uint8Array(args[0]), i); - i += args[0].byteLength; - args.shift(); - } - - return result.buffer; - }; - - function _arrayWithHoles(arr) { - if (Array.isArray(arr)) return arr; - } - - var arrayWithHoles = _arrayWithHoles; - - function _iterableToArrayLimit(arr, i) { - if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { - return; - } - - var _arr = []; - var _n = true; - var _d = false; - var _e = undefined; - - try { - for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { - _arr.push(_s.value); - - if (i && _arr.length === i) break; - } - } catch (err) { - _d = true; - _e = err; - } finally { - try { - if (!_n && _i["return"] != null) _i["return"](); - } finally { - if (_d) throw _e; - } - } - - return _arr; - } - - var iterableToArrayLimit = _iterableToArrayLimit; - - function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance"); - } - - var nonIterableRest = _nonIterableRest; - - function _slicedToArray(arr, i) { - return arrayWithHoles(arr) || iterableToArrayLimit(arr, i) || nonIterableRest(); - } - - var slicedToArray = _slicedToArray; - - var isClientKeyTicket = function isClientKeyTicket(ticket) { - var _ticket$split = ticket.split('@'), - _ticket$split2 = slicedToArray(_ticket$split, 1), - info = _ticket$split2[0]; - - var spnameFlagsOTP = info.split(':'); - - if (spnameFlagsOTP.length < 3) { - return false; - } - - var FLAGS_INDEX = 1; // second element of ticket — flags - - var flags = spnameFlagsOTP[FLAGS_INDEX]; - return flags.split('').some(function (element) { - return element === 'c'; - }); - }; - - var ticketAdapter = function ticketAdapter(response) { - if (response && response.data) { - var ticket = { - ticket: response.data, - ttl: response.ttl || 120 - }; - delete ticket.data; - return ticket; - } - - return response; - }; - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - var _typeof_1 = createCommonjsModule(function (module) { - function _typeof(obj) { - if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { - module.exports = _typeof = function _typeof(obj) { - return typeof obj; - }; - } else { - module.exports = _typeof = function _typeof(obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; - }; - } - - return _typeof(obj); - } - - module.exports = _typeof; - }); - - function _assertThisInitialized(self) { - if (self === void 0) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return self; - } - - var assertThisInitialized = _assertThisInitialized; - - function _possibleConstructorReturn(self, call) { - if (call && (_typeof_1(call) === "object" || typeof call === "function")) { - return call; - } - - return assertThisInitialized(self); - } - - var possibleConstructorReturn = _possibleConstructorReturn; - - var getPrototypeOf = createCommonjsModule(function (module) { - function _getPrototypeOf(o) { - module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { - return o.__proto__ || Object.getPrototypeOf(o); - }; - return _getPrototypeOf(o); - } - - module.exports = _getPrototypeOf; - }); - - var setPrototypeOf = createCommonjsModule(function (module) { - function _setPrototypeOf(o, p) { - module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { - o.__proto__ = p; - return o; - }; - - return _setPrototypeOf(o, p); - } - - module.exports = _setPrototypeOf; - }); - - function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function"); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - writable: true, - configurable: true - } - }); - if (superClass) setPrototypeOf(subClass, superClass); - } - - var inherits = _inherits; - - function _isNativeFunction(fn) { - return Function.toString.call(fn).indexOf("[native code]") !== -1; - } - - var isNativeFunction = _isNativeFunction; - - var construct = createCommonjsModule(function (module) { - function isNativeReflectConstruct() { - if (typeof Reflect === "undefined" || !Reflect.construct) return false; - if (Reflect.construct.sham) return false; - if (typeof Proxy === "function") return true; - - try { - Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); - return true; - } catch (e) { - return false; - } - } - - function _construct(Parent, args, Class) { - if (isNativeReflectConstruct()) { - module.exports = _construct = Reflect.construct; - } else { - module.exports = _construct = function _construct(Parent, args, Class) { - var a = [null]; - a.push.apply(a, args); - var Constructor = Function.bind.apply(Parent, a); - var instance = new Constructor(); - if (Class) setPrototypeOf(instance, Class.prototype); - return instance; - }; - } - - return _construct.apply(null, arguments); - } - - module.exports = _construct; - }); - - var wrapNativeSuper = createCommonjsModule(function (module) { - function _wrapNativeSuper(Class) { - var _cache = typeof Map === "function" ? new Map() : undefined; - - module.exports = _wrapNativeSuper = function _wrapNativeSuper(Class) { - if (Class === null || !isNativeFunction(Class)) return Class; - - if (typeof Class !== "function") { - throw new TypeError("Super expression must either be null or a function"); - } - - if (typeof _cache !== "undefined") { - if (_cache.has(Class)) return _cache.get(Class); - - _cache.set(Class, Wrapper); - } - - function Wrapper() { - return construct(Class, arguments, getPrototypeOf(this).constructor); - } - - Wrapper.prototype = Object.create(Class.prototype, { - constructor: { - value: Wrapper, - enumerable: false, - writable: true, - configurable: true - } - }); - return setPrototypeOf(Wrapper, Class); - }; - - return _wrapNativeSuper(Class); - } - - module.exports = _wrapNativeSuper; - }); - - var WWPassError = - /*#__PURE__*/ - function (_Error) { - inherits(WWPassError, _Error); - - function WWPassError(code) { - var _this; - - classCallCheck(this, WWPassError); - - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - _this = possibleConstructorReturn(this, getPrototypeOf(WWPassError).call(this, args, WWPassError)); - Error.captureStackTrace(assertThisInitialized(_this), WWPassError); - _this.code = code; - return _this; - } - - createClass(WWPassError, [{ - key: "toString", - value: function toString() { - return "".concat(this.name, "(").concat(this.code, "): ").concat(this.message); - } - }]); - - return WWPassError; - }(wrapNativeSuper(Error)); - - var exportKey = function exportKey(type, key) { - return subtle.exportKey(type, key); - }; // generate digest from string - - - var hex = function hex(buffer) { - var hexCodes = []; - var view = new DataView(buffer); - - for (var i = 0; i < view.byteLength; i += 4) { - // Using getUint32 reduces the number of iterations needed (we process 4 bytes each time) - var value = view.getUint32(i); // toString(16) will give the hex representation of the number without padding - - var stringValue = value.toString(16); // We use concatenation and slice for padding - - var padding = '00000000'; - var paddedValue = (padding + stringValue).slice(-padding.length); - hexCodes.push(paddedValue); - } // Join all the hex strings into one - - - return hexCodes.join(''); - }; // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest - - - var sha256 = function sha256(str) { - // We transform the string into an arraybuffer. - var buffer = str2ab(str); - return subtle.digest({ - name: 'SHA-256' - }, buffer).then(function (hash) { - return hex(hash); - }); - }; - - var clean = function clean(items) { - var currentDate = window.Date.now(); - return items.filter(function (item) { - return item.deadline > currentDate; - }); - }; - - var loadNonces = function loadNonces() { - var wwpassNonce = window.localStorage.getItem('wwpassNonce'); - - if (!wwpassNonce) { - return []; - } - - try { - return clean(JSON.parse(wwpassNonce)); - } catch (error) { - window.localStorage.removeItem('wwpassNonce'); - throw error; - } - }; - - var saveNonces = function saveNonces(nonces) { - window.localStorage.setItem('wwpassNonce', JSON.stringify(nonces)); - }; // get from localStorage Client Nonce - - - var getClientNonce = function getClientNonce(ticket) { - var newTTL = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - - if (!subtle) { - throw new WWPassError(WWPASS_STATUS.SSL_REQUIRED, 'Client-side encryption requires https.'); - } - - var nonces = loadNonces(); - return sha256(ticket).then(function (hash) { - var nonce = nonces.find(function (it) { - return hash === it.hash; - }); - var key = nonce && nonce.key ? b64ToAb(nonce.key) : undefined; - - if (newTTL && key) { - nonce.deadline = window.Date.now() + newTTL * 1000; - saveNonces(nonces); - } - - return key; - }); - }; // generate Client Nonce and set it to localStorage - - - var generateClientNonce = function generateClientNonce(ticket) { - var ttl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 120; - - if (!subtle) { - throw new WWPassError(WWPASS_STATUS.SSL_REQUIRED, 'Client-side encryption requires https.'); - } - - return getClientNonce(ticket).then(function (loadedKey) { - if (loadedKey) { - return loadedKey; - } - - return subtle.generateKey({ - name: 'AES-CBC', - length: 256 - }, true, // is extractable - ['encrypt', 'decrypt']).then(function (key) { - return exportKey('raw', key); - }).then(function (rawKey) { - return sha256(ticket).then(function (digest) { - var nonce = { - hash: digest, - key: abToB64(rawKey), - deadline: window.Date.now() + ttl * 1000 - }; - var nonces = loadNonces(); - nonces.push(nonce); - saveNonces(nonces); // hack for return key - - return rawKey; - }); - }); - }); - }; - - var getClientNonceWrapper = function getClientNonceWrapper(ticket) { - var ttl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 120; - - if (!isClientKeyTicket(ticket)) { - return new Promise(function (resolve) { - resolve(undefined); - }); - } - - return generateClientNonce(ticket, ttl); - }; - - var copyClientNonce = function copyClientNonce(oldTicket, newTicket, ttl) { - return getClientNonce(oldTicket).then(function (nonceKey) { - return sha256(newTicket) // eslint-disable-line max-len - .then(function (digest) { - var nonces = loadNonces(); - nonces.push({ - hash: digest, - key: abToB64(nonceKey), - deadline: window.Date.now() + ttl * 1000 - }); - saveNonces(nonces); - }); - }); - }; - - var clientKeyIV = new Uint8Array([176, 178, 97, 142, 156, 31, 45, 30, 81, 210, 85, 14, 202, 203, 86, 240]); - - var WWPassCryptoPromise = - /*#__PURE__*/ - function () { - createClass(WWPassCryptoPromise, [{ - key: "encryptArrayBuffer", - value: function encryptArrayBuffer(arrayBuffer) { - var iv = new Uint8Array(this.ivLen); - getRandomData(iv); - var algorithm = this.algorithm; - Object.assign(algorithm, { - iv: iv - }); - return encrypt(algorithm, this.clientKey, arrayBuffer).then(function (encryptedAB) { - return concatBuffers(iv.buffer, encryptedAB); - }); - } - }, { - key: "encryptString", - value: function encryptString(string) { - return this.encryptArrayBuffer(str2ab(string)).then(abToB64); - } - }, { - key: "decryptArrayBuffer", - value: function decryptArrayBuffer(encryptedArrayBuffer) { - var algorithm = this.algorithm; - Object.assign(algorithm, { - iv: encryptedArrayBuffer.slice(0, this.ivLen) - }); - return decrypt(algorithm, this.clientKey, encryptedArrayBuffer.slice(this.ivLen)); - } - }, { - key: "decryptString", - value: function decryptString(encryptedString) { - return this.decryptArrayBuffer(b64ToAb(encryptedString)).then(ab2str); - } // Private - - }], [{ - key: "getWWPassCrypto", - - /* Return Promise that will be resloved to catual crypto object - with encrypt/decrypt String/ArrayBuffer methods and cleintKey member. - Ticket must be authenticated with 'c' auth factor. - Only supported values for algorithm are 'AES-GCM' and 'AES-CBC'. - */ - value: function getWWPassCrypto(ticket) { - var algorithmName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'AES-GCM'; - var encryptedClientKey = null; - var algorithm = { - name: algorithmName, - length: 256 - }; - return getWebSocketResult({ - ticket: ticket, - clientKeyOnly: true - }).then(function (result) { - if (!result.clientKey) { - throw Error("No client key associated with the ticket ".concat(ticket)); - } - - encryptedClientKey = result.clientKey; - return getClientNonce(result.originalTicket ? result.originalTicket : ticket, result.ttl); - }).then(function (key) { - if (!key) { - throw new Error('No client key nonce associated with the ticket in this browser'); - } - - return importKey('raw', key, { - name: 'AES-CBC' - }, false, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']); - }).then(function (clientKeyNonce) { - return decrypt({ - name: 'AES-CBC', - iv: clientKeyIV - }, clientKeyNonce, b64ToAb(encryptedClientKey)); - }).then(function (arrayBuffer) { - return importKey('raw', arrayBuffer, algorithm, false, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']); - }).then(function (key) { - return new WWPassCryptoPromise(key, algorithm); - }).catch(function (error) { - if (error.reason !== undefined) { - throw new Error(error.reason); - } - - throw error; - }); - } - }]); - - function WWPassCryptoPromise(key, algorithm) { - classCallCheck(this, WWPassCryptoPromise); - - this.ivLen = algorithm.name === 'AES-GCM' ? 12 : 16; - this.algorithm = algorithm; - - if (algorithm.name === 'AES-GCM') { - Object.assign(this.algorithm, { - tagLength: 128 - }); - } - - this.clientKey = key; - } - - return WWPassCryptoPromise; - }(); - - var runtime_1 = createCommonjsModule(function (module) { - /** - * Copyright (c) 2014-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - - var runtime = (function (exports) { - - var Op = Object.prototype; - var hasOwn = Op.hasOwnProperty; - var undefined$1; // More compressible than void 0. - var $Symbol = typeof Symbol === "function" ? Symbol : {}; - var iteratorSymbol = $Symbol.iterator || "@@iterator"; - var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; - var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; - - function wrap(innerFn, outerFn, self, tryLocsList) { - // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator. - var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; - var generator = Object.create(protoGenerator.prototype); - var context = new Context(tryLocsList || []); - - // The ._invoke method unifies the implementations of the .next, - // .throw, and .return methods. - generator._invoke = makeInvokeMethod(innerFn, self, context); - - return generator; - } - exports.wrap = wrap; - - // Try/catch helper to minimize deoptimizations. Returns a completion - // record like context.tryEntries[i].completion. This interface could - // have been (and was previously) designed to take a closure to be - // invoked without arguments, but in all the cases we care about we - // already have an existing method we want to call, so there's no need - // to create a new function object. We can even get away with assuming - // the method takes exactly one argument, since that happens to be true - // in every case, so we don't have to touch the arguments object. The - // only additional allocation required is the completion record, which - // has a stable shape and so hopefully should be cheap to allocate. - function tryCatch(fn, obj, arg) { - try { - return { type: "normal", arg: fn.call(obj, arg) }; - } catch (err) { - return { type: "throw", arg: err }; - } - } - - var GenStateSuspendedStart = "suspendedStart"; - var GenStateSuspendedYield = "suspendedYield"; - var GenStateExecuting = "executing"; - var GenStateCompleted = "completed"; - - // Returning this object from the innerFn has the same effect as - // breaking out of the dispatch switch statement. - var ContinueSentinel = {}; - - // Dummy constructor functions that we use as the .constructor and - // .constructor.prototype properties for functions that return Generator - // objects. For full spec compliance, you may wish to configure your - // minifier not to mangle the names of these two functions. - function Generator() {} - function GeneratorFunction() {} - function GeneratorFunctionPrototype() {} - - // This is a polyfill for %IteratorPrototype% for environments that - // don't natively support it. - var IteratorPrototype = {}; - IteratorPrototype[iteratorSymbol] = function () { - return this; - }; - - var getProto = Object.getPrototypeOf; - var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); - if (NativeIteratorPrototype && - NativeIteratorPrototype !== Op && - hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) { - // This environment has a native %IteratorPrototype%; use it instead - // of the polyfill. - IteratorPrototype = NativeIteratorPrototype; - } - - var Gp = GeneratorFunctionPrototype.prototype = - Generator.prototype = Object.create(IteratorPrototype); - GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; - GeneratorFunctionPrototype.constructor = GeneratorFunction; - GeneratorFunctionPrototype[toStringTagSymbol] = - GeneratorFunction.displayName = "GeneratorFunction"; - - // Helper for defining the .next, .throw, and .return methods of the - // Iterator interface in terms of a single ._invoke method. - function defineIteratorMethods(prototype) { - ["next", "throw", "return"].forEach(function(method) { - prototype[method] = function(arg) { - return this._invoke(method, arg); - }; - }); - } - - exports.isGeneratorFunction = function(genFun) { - var ctor = typeof genFun === "function" && genFun.constructor; - return ctor - ? ctor === GeneratorFunction || - // For the native GeneratorFunction constructor, the best we can - // do is to check its .name property. - (ctor.displayName || ctor.name) === "GeneratorFunction" - : false; - }; - - exports.mark = function(genFun) { - if (Object.setPrototypeOf) { - Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); - } else { - genFun.__proto__ = GeneratorFunctionPrototype; - if (!(toStringTagSymbol in genFun)) { - genFun[toStringTagSymbol] = "GeneratorFunction"; - } - } - genFun.prototype = Object.create(Gp); - return genFun; - }; - - // Within the body of any async function, `await x` is transformed to - // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test - // `hasOwn.call(value, "__await")` to determine if the yielded value is - // meant to be awaited. - exports.awrap = function(arg) { - return { __await: arg }; - }; - - function AsyncIterator(generator) { - function invoke(method, arg, resolve, reject) { - var record = tryCatch(generator[method], generator, arg); - if (record.type === "throw") { - reject(record.arg); - } else { - var result = record.arg; - var value = result.value; - if (value && - typeof value === "object" && - hasOwn.call(value, "__await")) { - return Promise.resolve(value.__await).then(function(value) { - invoke("next", value, resolve, reject); - }, function(err) { - invoke("throw", err, resolve, reject); - }); - } - - return Promise.resolve(value).then(function(unwrapped) { - // When a yielded Promise is resolved, its final value becomes - // the .value of the Promise<{value,done}> result for the - // current iteration. - result.value = unwrapped; - resolve(result); - }, function(error) { - // If a rejected Promise was yielded, throw the rejection back - // into the async generator function so it can be handled there. - return invoke("throw", error, resolve, reject); - }); - } - } - - var previousPromise; - - function enqueue(method, arg) { - function callInvokeWithMethodAndArg() { - return new Promise(function(resolve, reject) { - invoke(method, arg, resolve, reject); - }); - } - - return previousPromise = - // If enqueue has been called before, then we want to wait until - // all previous Promises have been resolved before calling invoke, - // so that results are always delivered in the correct order. If - // enqueue has not been called before, then it is important to - // call invoke immediately, without waiting on a callback to fire, - // so that the async generator function has the opportunity to do - // any necessary setup in a predictable way. This predictability - // is why the Promise constructor synchronously invokes its - // executor callback, and why async functions synchronously - // execute code before the first await. Since we implement simple - // async functions in terms of async generators, it is especially - // important to get this right, even though it requires care. - previousPromise ? previousPromise.then( - callInvokeWithMethodAndArg, - // Avoid propagating failures to Promises returned by later - // invocations of the iterator. - callInvokeWithMethodAndArg - ) : callInvokeWithMethodAndArg(); - } - - // Define the unified helper method that is used to implement .next, - // .throw, and .return (see defineIteratorMethods). - this._invoke = enqueue; - } - - defineIteratorMethods(AsyncIterator.prototype); - AsyncIterator.prototype[asyncIteratorSymbol] = function () { - return this; - }; - exports.AsyncIterator = AsyncIterator; - - // Note that simple async functions are implemented on top of - // AsyncIterator objects; they just return a Promise for the value of - // the final result produced by the iterator. - exports.async = function(innerFn, outerFn, self, tryLocsList) { - var iter = new AsyncIterator( - wrap(innerFn, outerFn, self, tryLocsList) - ); - - return exports.isGeneratorFunction(outerFn) - ? iter // If outerFn is a generator, return the full iterator. - : iter.next().then(function(result) { - return result.done ? result.value : iter.next(); - }); - }; - - function makeInvokeMethod(innerFn, self, context) { - var state = GenStateSuspendedStart; - - return function invoke(method, arg) { - if (state === GenStateExecuting) { - throw new Error("Generator is already running"); - } - - if (state === GenStateCompleted) { - if (method === "throw") { - throw arg; - } - - // Be forgiving, per 25.3.3.3.3 of the spec: - // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume - return doneResult(); - } - - context.method = method; - context.arg = arg; - - while (true) { - var delegate = context.delegate; - if (delegate) { - var delegateResult = maybeInvokeDelegate(delegate, context); - if (delegateResult) { - if (delegateResult === ContinueSentinel) continue; - return delegateResult; - } - } - - if (context.method === "next") { - // Setting context._sent for legacy support of Babel's - // function.sent implementation. - context.sent = context._sent = context.arg; - - } else if (context.method === "throw") { - if (state === GenStateSuspendedStart) { - state = GenStateCompleted; - throw context.arg; - } - - context.dispatchException(context.arg); - - } else if (context.method === "return") { - context.abrupt("return", context.arg); - } - - state = GenStateExecuting; - - var record = tryCatch(innerFn, self, context); - if (record.type === "normal") { - // If an exception is thrown from innerFn, we leave state === - // GenStateExecuting and loop back for another invocation. - state = context.done - ? GenStateCompleted - : GenStateSuspendedYield; - - if (record.arg === ContinueSentinel) { - continue; - } - - return { - value: record.arg, - done: context.done - }; - - } else if (record.type === "throw") { - state = GenStateCompleted; - // Dispatch the exception by looping back around to the - // context.dispatchException(context.arg) call above. - context.method = "throw"; - context.arg = record.arg; - } - } - }; - } - - // Call delegate.iterator[context.method](context.arg) and handle the - // result, either by returning a { value, done } result from the - // delegate iterator, or by modifying context.method and context.arg, - // setting context.delegate to null, and returning the ContinueSentinel. - function maybeInvokeDelegate(delegate, context) { - var method = delegate.iterator[context.method]; - if (method === undefined$1) { - // A .throw or .return when the delegate iterator has no .throw - // method always terminates the yield* loop. - context.delegate = null; - - if (context.method === "throw") { - // Note: ["return"] must be used for ES3 parsing compatibility. - if (delegate.iterator["return"]) { - // If the delegate iterator has a return method, give it a - // chance to clean up. - context.method = "return"; - context.arg = undefined$1; - maybeInvokeDelegate(delegate, context); - - if (context.method === "throw") { - // If maybeInvokeDelegate(context) changed context.method from - // "return" to "throw", let that override the TypeError below. - return ContinueSentinel; - } - } - - context.method = "throw"; - context.arg = new TypeError( - "The iterator does not provide a 'throw' method"); - } - - return ContinueSentinel; - } - - var record = tryCatch(method, delegate.iterator, context.arg); - - if (record.type === "throw") { - context.method = "throw"; - context.arg = record.arg; - context.delegate = null; - return ContinueSentinel; - } - - var info = record.arg; - - if (! info) { - context.method = "throw"; - context.arg = new TypeError("iterator result is not an object"); - context.delegate = null; - return ContinueSentinel; - } - - if (info.done) { - // Assign the result of the finished delegate to the temporary - // variable specified by delegate.resultName (see delegateYield). - context[delegate.resultName] = info.value; - - // Resume execution at the desired location (see delegateYield). - context.next = delegate.nextLoc; - - // If context.method was "throw" but the delegate handled the - // exception, let the outer generator proceed normally. If - // context.method was "next", forget context.arg since it has been - // "consumed" by the delegate iterator. If context.method was - // "return", allow the original .return call to continue in the - // outer generator. - if (context.method !== "return") { - context.method = "next"; - context.arg = undefined$1; - } - - } else { - // Re-yield the result returned by the delegate method. - return info; - } - - // The delegate iterator is finished, so forget it and continue with - // the outer generator. - context.delegate = null; - return ContinueSentinel; - } - - // Define Generator.prototype.{next,throw,return} in terms of the - // unified ._invoke helper method. - defineIteratorMethods(Gp); - - Gp[toStringTagSymbol] = "Generator"; - - // A Generator should always return itself as the iterator object when the - // @@iterator function is called on it. Some browsers' implementations of the - // iterator prototype chain incorrectly implement this, causing the Generator - // object to not be returned from this call. This ensures that doesn't happen. - // See https://github.com/facebook/regenerator/issues/274 for more details. - Gp[iteratorSymbol] = function() { - return this; - }; - - Gp.toString = function() { - return "[object Generator]"; - }; - - function pushTryEntry(locs) { - var entry = { tryLoc: locs[0] }; - - if (1 in locs) { - entry.catchLoc = locs[1]; - } - - if (2 in locs) { - entry.finallyLoc = locs[2]; - entry.afterLoc = locs[3]; - } - - this.tryEntries.push(entry); - } - - function resetTryEntry(entry) { - var record = entry.completion || {}; - record.type = "normal"; - delete record.arg; - entry.completion = record; - } - - function Context(tryLocsList) { - // The root entry object (effectively a try statement without a catch - // or a finally block) gives us a place to store values thrown from - // locations where there is no enclosing try statement. - this.tryEntries = [{ tryLoc: "root" }]; - tryLocsList.forEach(pushTryEntry, this); - this.reset(true); - } - - exports.keys = function(object) { - var keys = []; - for (var key in object) { - keys.push(key); - } - keys.reverse(); - - // Rather than returning an object with a next method, we keep - // things simple and return the next function itself. - return function next() { - while (keys.length) { - var key = keys.pop(); - if (key in object) { - next.value = key; - next.done = false; - return next; - } - } - - // To avoid creating an additional object, we just hang the .value - // and .done properties off the next function object itself. This - // also ensures that the minifier will not anonymize the function. - next.done = true; - return next; - }; - }; - - function values(iterable) { - if (iterable) { - var iteratorMethod = iterable[iteratorSymbol]; - if (iteratorMethod) { - return iteratorMethod.call(iterable); - } - - if (typeof iterable.next === "function") { - return iterable; - } - - if (!isNaN(iterable.length)) { - var i = -1, next = function next() { - while (++i < iterable.length) { - if (hasOwn.call(iterable, i)) { - next.value = iterable[i]; - next.done = false; - return next; - } - } - - next.value = undefined$1; - next.done = true; - - return next; - }; - - return next.next = next; - } - } - - // Return an iterator with no values. - return { next: doneResult }; - } - exports.values = values; - - function doneResult() { - return { value: undefined$1, done: true }; - } - - Context.prototype = { - constructor: Context, - - reset: function(skipTempReset) { - this.prev = 0; - this.next = 0; - // Resetting context._sent for legacy support of Babel's - // function.sent implementation. - this.sent = this._sent = undefined$1; - this.done = false; - this.delegate = null; - - this.method = "next"; - this.arg = undefined$1; - - this.tryEntries.forEach(resetTryEntry); - - if (!skipTempReset) { - for (var name in this) { - // Not sure about the optimal order of these conditions: - if (name.charAt(0) === "t" && - hasOwn.call(this, name) && - !isNaN(+name.slice(1))) { - this[name] = undefined$1; - } - } - } - }, - - stop: function() { - this.done = true; - - var rootEntry = this.tryEntries[0]; - var rootRecord = rootEntry.completion; - if (rootRecord.type === "throw") { - throw rootRecord.arg; - } - - return this.rval; - }, - - dispatchException: function(exception) { - if (this.done) { - throw exception; - } - - var context = this; - function handle(loc, caught) { - record.type = "throw"; - record.arg = exception; - context.next = loc; - - if (caught) { - // If the dispatched exception was caught by a catch block, - // then let that catch block handle the exception normally. - context.method = "next"; - context.arg = undefined$1; - } - - return !! caught; - } - - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - var record = entry.completion; - - if (entry.tryLoc === "root") { - // Exception thrown outside of any try block that could handle - // it, so set the completion value of the entire function to - // throw the exception. - return handle("end"); - } - - if (entry.tryLoc <= this.prev) { - var hasCatch = hasOwn.call(entry, "catchLoc"); - var hasFinally = hasOwn.call(entry, "finallyLoc"); - - if (hasCatch && hasFinally) { - if (this.prev < entry.catchLoc) { - return handle(entry.catchLoc, true); - } else if (this.prev < entry.finallyLoc) { - return handle(entry.finallyLoc); - } - - } else if (hasCatch) { - if (this.prev < entry.catchLoc) { - return handle(entry.catchLoc, true); - } - - } else if (hasFinally) { - if (this.prev < entry.finallyLoc) { - return handle(entry.finallyLoc); - } - - } else { - throw new Error("try statement without catch or finally"); - } - } - } - }, - - abrupt: function(type, arg) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.tryLoc <= this.prev && - hasOwn.call(entry, "finallyLoc") && - this.prev < entry.finallyLoc) { - var finallyEntry = entry; - break; - } - } - - if (finallyEntry && - (type === "break" || - type === "continue") && - finallyEntry.tryLoc <= arg && - arg <= finallyEntry.finallyLoc) { - // Ignore the finally entry if control is not jumping to a - // location outside the try/catch block. - finallyEntry = null; - } - - var record = finallyEntry ? finallyEntry.completion : {}; - record.type = type; - record.arg = arg; - - if (finallyEntry) { - this.method = "next"; - this.next = finallyEntry.finallyLoc; - return ContinueSentinel; - } - - return this.complete(record); - }, - - complete: function(record, afterLoc) { - if (record.type === "throw") { - throw record.arg; - } - - if (record.type === "break" || - record.type === "continue") { - this.next = record.arg; - } else if (record.type === "return") { - this.rval = this.arg = record.arg; - this.method = "return"; - this.next = "end"; - } else if (record.type === "normal" && afterLoc) { - this.next = afterLoc; - } - - return ContinueSentinel; - }, - - finish: function(finallyLoc) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.finallyLoc === finallyLoc) { - this.complete(entry.completion, entry.afterLoc); - resetTryEntry(entry); - return ContinueSentinel; - } - } - }, - - "catch": function(tryLoc) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.tryLoc === tryLoc) { - var record = entry.completion; - if (record.type === "throw") { - var thrown = record.arg; - resetTryEntry(entry); - } - return thrown; - } - } - - // The context.catch method must only be called with a location - // argument that corresponds to a known catch block. - throw new Error("illegal catch attempt"); - }, - - delegateYield: function(iterable, resultName, nextLoc) { - this.delegate = { - iterator: values(iterable), - resultName: resultName, - nextLoc: nextLoc - }; - - if (this.method === "next") { - // Deliberately forget the last sent value so that we don't - // accidentally pass it on to the delegate. - this.arg = undefined$1; - } - - return ContinueSentinel; - } - }; - - // Regardless of whether this script is executing as a CommonJS module - // or not, return the runtime object so that we can declare the variable - // regeneratorRuntime in the outer scope, which allows this module to be - // injected easily by `bin/regenerator --include-runtime script.js`. - return exports; - - }( - // If this script is executing as a CommonJS module, use module.exports - // as the regeneratorRuntime namespace. Otherwise create a new empty - // object. Either way, the resulting object will be used to initialize - // the regeneratorRuntime variable at the top of this file. - module.exports - )); - - try { - regeneratorRuntime = runtime; - } catch (accidentalStrictMode) { - // This module should not be running in strict mode, so the above - // assignment should always work unless something is misconfigured. Just - // in case runtime.js accidentally runs in strict mode, we can escape - // strict mode using a global Function call. This could conceivably fail - // if a Content Security Policy forbids using Function, but in that case - // the proper solution is to fix the accidental strict mode problem. If - // you've misconfigured your bundler to force strict mode and applied a - // CSP to forbid Function, and you're not willing to fix either of those - // problems, please detail your unique predicament in a GitHub issue. - Function("r", "regeneratorRuntime = r")(runtime); - } - }); - - var regenerator = runtime_1; - - function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { - try { - var info = gen[key](arg); - var value = info.value; - } catch (error) { - reject(error); - return; - } - - if (info.done) { - resolve(value); - } else { - Promise.resolve(value).then(_next, _throw); - } - } - - function _asyncToGenerator(fn) { - return function () { - var self = this, - args = arguments; - return new Promise(function (resolve, reject) { - var gen = fn.apply(self, args); - - function _next(value) { - asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); - } - - function _throw(err) { - asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); - } - - _next(undefined); - }); - }; - } - - var asyncToGenerator = _asyncToGenerator; - - var noCacheHeaders = { - pragma: 'no-cache', - 'cache-control': 'no-cache' - }; - - var getTicket = function getTicket(url) { - return fetch(url, { - cache: 'no-store', - headers: noCacheHeaders - }).then(function (response) { - if (!response.ok) { - throw Error("Error fetching ticket from \"".concat(url, "\": ").concat(response.statusText)); - } - - return response.json(); - }); - }; - /* updateTicket should be called when the client wants to extend the session beyond - ticket's TTL. The URL handler on the server should use putTicket to get new ticket - whith the same credentials as the old one. The URL should return JSON object: - {"oldTicket": "", "newTicket": "", "ttl": } - The functions ultimately resolves to: - {"ticket": "", "ttl": } - */ - - - var updateTicket = function updateTicket(url) { - return fetch(url, { - cache: 'no-store', - headers: noCacheHeaders - }).then(function (response) { - if (!response.ok) { - throw Error("Error updating ticket from \"".concat(url, "\": ").concat(response.statusText)); - } - - return response.json(); - }).then(function (response) { - if (!response.newTicket || !response.oldTicket || !response.ttl) { - throw Error("Invalid response ot updateTicket: ".concat(response)); - } - - var result = { - ticket: response.newTicket, - ttl: response.ttl - }; - - if (!isClientKeyTicket(response.newTicket)) { - return result; - } // We have to call getWebSocketResult and getClientNonce to check for Nonce and update - // TTL on original ticket - - - return getWebSocketResult({ - ticket: response.newTicket, - clientKeyOnly: true - }).then(function (wsResult) { - if (!wsResult.clientKey) { - throw Error("No client key associated with the ticket ".concat(response.newTicket)); - } - - return getClientNonce(wsResult.originalTicket ? wsResult.originalTicket : response.newTicket, wsResult.ttl); - }).then(function () { - return result; - }); - }); - }; - - var toString = {}.toString; - - var isarray = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; - }; - - var K_MAX_LENGTH = 0x7fffffff; - - function Buffer (arg, offset, length) { - if (typeof arg === 'number') { - return allocUnsafe(arg) - } - - return from(arg, offset, length) - } - - Buffer.prototype.__proto__ = Uint8Array.prototype; - Buffer.__proto__ = Uint8Array; - - // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 - if (typeof Symbol !== 'undefined' && Symbol.species && - Buffer[Symbol.species] === Buffer) { - Object.defineProperty(Buffer, Symbol.species, { - value: null, - configurable: true, - enumerable: false, - writable: false - }); - } - - function checked (length) { - // Note: cannot use `length < K_MAX_LENGTH` here because that fails when - // length is NaN (which is otherwise coerced to zero.) - if (length >= K_MAX_LENGTH) { - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') - } - return length | 0 - } - - function isnan (val) { - return val !== val // eslint-disable-line no-self-compare - } - - function createBuffer (length) { - var buf = new Uint8Array(length); - buf.__proto__ = Buffer.prototype; - return buf - } - - function allocUnsafe (size) { - return createBuffer(size < 0 ? 0 : checked(size) | 0) - } - - function fromString (string) { - var length = byteLength(string) | 0; - var buf = createBuffer(length); - - var actual = buf.write(string); - - if (actual !== length) { - // Writing a hex string, for example, that contains invalid characters will - // cause everything after the first invalid character to be ignored. (e.g. - // 'abxxcd' will be treated as 'ab') - buf = buf.slice(0, actual); - } - - return buf - } - - function fromArrayLike (array) { - var length = array.length < 0 ? 0 : checked(array.length) | 0; - var buf = createBuffer(length); - for (var i = 0; i < length; i += 1) { - buf[i] = array[i] & 255; - } - return buf - } - - function fromArrayBuffer (array, byteOffset, length) { - if (byteOffset < 0 || array.byteLength < byteOffset) { - throw new RangeError('\'offset\' is out of bounds') - } - - if (array.byteLength < byteOffset + (length || 0)) { - throw new RangeError('\'length\' is out of bounds') - } - - var buf; - if (byteOffset === undefined && length === undefined) { - buf = new Uint8Array(array); - } else if (length === undefined) { - buf = new Uint8Array(array, byteOffset); - } else { - buf = new Uint8Array(array, byteOffset, length); - } - - // Return an augmented `Uint8Array` instance - buf.__proto__ = Buffer.prototype; - return buf - } - - function fromObject (obj) { - if (Buffer.isBuffer(obj)) { - var len = checked(obj.length) | 0; - var buf = createBuffer(len); - - if (buf.length === 0) { - return buf - } - - obj.copy(buf, 0, 0, len); - return buf - } - - if (obj) { - if ((typeof ArrayBuffer !== 'undefined' && - obj.buffer instanceof ArrayBuffer) || 'length' in obj) { - if (typeof obj.length !== 'number' || isnan(obj.length)) { - return createBuffer(0) - } - return fromArrayLike(obj) - } - - if (obj.type === 'Buffer' && Array.isArray(obj.data)) { - return fromArrayLike(obj.data) - } - } - - throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') - } - - function utf8ToBytes (string, units) { - units = units || Infinity; - var codePoint; - var length = string.length; - var leadSurrogate = null; - var bytes = []; - - for (var i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i); - - // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xDBFF) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); - continue - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); - continue - } - - // valid lead - leadSurrogate = codePoint; - - continue - } - - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); - leadSurrogate = codePoint; - continue - } - - // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000; - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); - } - - leadSurrogate = null; - - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint); - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ); - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ); - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ); - } else { - throw new Error('Invalid code point') - } - } - - return bytes - } - - function byteLength (string) { - if (Buffer.isBuffer(string)) { - return string.length - } - if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && - (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { - return string.byteLength - } - if (typeof string !== 'string') { - string = '' + string; - } - - var len = string.length; - if (len === 0) return 0 - - return utf8ToBytes(string).length - } - - function blitBuffer (src, dst, offset, length) { - for (var i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break - dst[i + offset] = src[i]; - } - return i - } - - function utf8Write (buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) - } - - function from (value, offset, length) { - if (typeof value === 'number') { - throw new TypeError('"value" argument must not be a number') - } - - if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { - return fromArrayBuffer(value, offset, length) - } - - if (typeof value === 'string') { - return fromString(value, offset) - } - - return fromObject(value) - } - - Buffer.prototype.write = function write (string, offset, length) { - // Buffer#write(string) - if (offset === undefined) { - length = this.length; - offset = 0; - // Buffer#write(string, encoding) - } else if (length === undefined && typeof offset === 'string') { - length = this.length; - offset = 0; - // Buffer#write(string, offset[, length]) - } else if (isFinite(offset)) { - offset = offset | 0; - if (isFinite(length)) { - length = length | 0; - } else { - length = undefined; - } - } - - var remaining = this.length - offset; - if (length === undefined || length > remaining) length = remaining; - - if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { - throw new RangeError('Attempt to write outside buffer bounds') - } - - return utf8Write(this, string, offset, length) - }; - - Buffer.prototype.slice = function slice (start, end) { - var len = this.length; - start = ~~start; - end = end === undefined ? len : ~~end; - - if (start < 0) { - start += len; - if (start < 0) start = 0; - } else if (start > len) { - start = len; - } - - if (end < 0) { - end += len; - if (end < 0) end = 0; - } else if (end > len) { - end = len; - } - - if (end < start) end = start; - - var newBuf = this.subarray(start, end); - // Return an augmented `Uint8Array` instance - newBuf.__proto__ = Buffer.prototype; - return newBuf - }; - - Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!start) start = 0; - if (!end && end !== 0) end = this.length; - if (targetStart >= target.length) targetStart = target.length; - if (!targetStart) targetStart = 0; - if (end > 0 && end < start) end = start; - - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 - - // Fatal error conditions - if (targetStart < 0) { - throw new RangeError('targetStart out of bounds') - } - if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') - if (end < 0) throw new RangeError('sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) end = this.length; - if (target.length - targetStart < end - start) { - end = target.length - targetStart + start; - } - - var len = end - start; - var i; - - if (this === target && start < targetStart && targetStart < end) { - // descending copy from end - for (i = len - 1; i >= 0; --i) { - target[i + targetStart] = this[i + start]; - } - } else if (len < 1000) { - // ascending copy from start - for (i = 0; i < len; ++i) { - target[i + targetStart] = this[i + start]; - } - } else { - Uint8Array.prototype.set.call( - target, - this.subarray(start, start + len), - targetStart - ); - } - - return len - }; - - Buffer.prototype.fill = function fill (val, start, end) { - // Handle string cases: - if (typeof val === 'string') { - if (typeof start === 'string') { - start = 0; - end = this.length; - } else if (typeof end === 'string') { - end = this.length; - } - if (val.length === 1) { - var code = val.charCodeAt(0); - if (code < 256) { - val = code; - } - } - } else if (typeof val === 'number') { - val = val & 255; - } - - // Invalid ranges are not set to a default, so can range check early. - if (start < 0 || this.length < start || this.length < end) { - throw new RangeError('Out of range index') - } - - if (end <= start) { - return this - } - - start = start >>> 0; - end = end === undefined ? this.length : end >>> 0; - - if (!val) val = 0; - - var i; - if (typeof val === 'number') { - for (i = start; i < end; ++i) { - this[i] = val; - } - } else { - var bytes = Buffer.isBuffer(val) - ? val - : new Buffer(val); - var len = bytes.length; - for (i = 0; i < end - start; ++i) { - this[i + start] = bytes[i % len]; - } - } - - return this - }; - - Buffer.concat = function concat (list, length) { - if (!isarray(list)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - - if (list.length === 0) { - return createBuffer(null, 0) - } - - var i; - if (length === undefined) { - length = 0; - for (i = 0; i < list.length; ++i) { - length += list[i].length; - } - } - - var buffer = allocUnsafe(length); - var pos = 0; - for (i = 0; i < list.length; ++i) { - var buf = list[i]; - if (!Buffer.isBuffer(buf)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - buf.copy(buffer, pos); - pos += buf.length; - } - return buffer - }; - - Buffer.byteLength = byteLength; - - Buffer.prototype._isBuffer = true; - Buffer.isBuffer = function isBuffer (b) { - return !!(b != null && b._isBuffer) - }; - - var typedarrayBuffer = Buffer; - - var toSJISFunction; - var CODEWORDS_COUNT = [ - 0, // Not used - 26, 44, 70, 100, 134, 172, 196, 242, 292, 346, - 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085, - 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185, - 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706 - ]; - - /** - * Returns the QR Code size for the specified version - * - * @param {Number} version QR Code version - * @return {Number} size of QR code - */ - var getSymbolSize = function getSymbolSize (version) { - if (!version) throw new Error('"version" cannot be null or undefined') - if (version < 1 || version > 40) throw new Error('"version" should be in range from 1 to 40') - return version * 4 + 17 - }; - - /** - * Returns the total number of codewords used to store data and EC information. - * - * @param {Number} version QR Code version - * @return {Number} Data length in bits - */ - var getSymbolTotalCodewords = function getSymbolTotalCodewords (version) { - return CODEWORDS_COUNT[version] - }; - - /** - * Encode data with Bose-Chaudhuri-Hocquenghem - * - * @param {Number} data Value to encode - * @return {Number} Encoded value - */ - var getBCHDigit = function (data) { - var digit = 0; - - while (data !== 0) { - digit++; - data >>>= 1; - } - - return digit - }; - - var setToSJISFunction = function setToSJISFunction (f) { - if (typeof f !== 'function') { - throw new Error('"toSJISFunc" is not a valid function.') - } - - toSJISFunction = f; - }; - - var isKanjiModeEnabled = function () { - return typeof toSJISFunction !== 'undefined' - }; - - var toSJIS = function toSJIS (kanji) { - return toSJISFunction(kanji) - }; - - var utils = { - getSymbolSize: getSymbolSize, - getSymbolTotalCodewords: getSymbolTotalCodewords, - getBCHDigit: getBCHDigit, - setToSJISFunction: setToSJISFunction, - isKanjiModeEnabled: isKanjiModeEnabled, - toSJIS: toSJIS - }; - - var errorCorrectionLevel = createCommonjsModule(function (module, exports) { - exports.L = { bit: 1 }; - exports.M = { bit: 0 }; - exports.Q = { bit: 3 }; - exports.H = { bit: 2 }; - - function fromString (string) { - if (typeof string !== 'string') { - throw new Error('Param is not a string') - } - - var lcStr = string.toLowerCase(); - - switch (lcStr) { - case 'l': - case 'low': - return exports.L - - case 'm': - case 'medium': - return exports.M - - case 'q': - case 'quartile': - return exports.Q - - case 'h': - case 'high': - return exports.H - - default: - throw new Error('Unknown EC Level: ' + string) - } - } - - exports.isValid = function isValid (level) { - return level && typeof level.bit !== 'undefined' && - level.bit >= 0 && level.bit < 4 - }; - - exports.from = function from (value, defaultValue) { - if (exports.isValid(value)) { - return value - } - - try { - return fromString(value) - } catch (e) { - return defaultValue - } - }; - }); - var errorCorrectionLevel_1 = errorCorrectionLevel.L; - var errorCorrectionLevel_2 = errorCorrectionLevel.M; - var errorCorrectionLevel_3 = errorCorrectionLevel.Q; - var errorCorrectionLevel_4 = errorCorrectionLevel.H; - var errorCorrectionLevel_5 = errorCorrectionLevel.isValid; - - function BitBuffer () { - this.buffer = []; - this.length = 0; - } - - BitBuffer.prototype = { - - get: function (index) { - var bufIndex = Math.floor(index / 8); - return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1 - }, - - put: function (num, length) { - for (var i = 0; i < length; i++) { - this.putBit(((num >>> (length - i - 1)) & 1) === 1); - } - }, - - getLengthInBits: function () { - return this.length - }, - - putBit: function (bit) { - var bufIndex = Math.floor(this.length / 8); - if (this.buffer.length <= bufIndex) { - this.buffer.push(0); - } - - if (bit) { - this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)); - } - - this.length++; - } - }; - - var bitBuffer = BitBuffer; - - /** - * Helper class to handle QR Code symbol modules - * - * @param {Number} size Symbol size - */ - function BitMatrix (size) { - if (!size || size < 1) { - throw new Error('BitMatrix size must be defined and greater than 0') - } - - this.size = size; - this.data = new typedarrayBuffer(size * size); - this.data.fill(0); - this.reservedBit = new typedarrayBuffer(size * size); - this.reservedBit.fill(0); - } - - /** - * Set bit value at specified location - * If reserved flag is set, this bit will be ignored during masking process - * - * @param {Number} row - * @param {Number} col - * @param {Boolean} value - * @param {Boolean} reserved - */ - BitMatrix.prototype.set = function (row, col, value, reserved) { - var index = row * this.size + col; - this.data[index] = value; - if (reserved) this.reservedBit[index] = true; - }; - - /** - * Returns bit value at specified location - * - * @param {Number} row - * @param {Number} col - * @return {Boolean} - */ - BitMatrix.prototype.get = function (row, col) { - return this.data[row * this.size + col] - }; - - /** - * Applies xor operator at specified location - * (used during masking process) - * - * @param {Number} row - * @param {Number} col - * @param {Boolean} value - */ - BitMatrix.prototype.xor = function (row, col, value) { - this.data[row * this.size + col] ^= value; - }; - - /** - * Check if bit at specified location is reserved - * - * @param {Number} row - * @param {Number} col - * @return {Boolean} - */ - BitMatrix.prototype.isReserved = function (row, col) { - return this.reservedBit[row * this.size + col] - }; - - var bitMatrix = BitMatrix; - - var alignmentPattern = createCommonjsModule(function (module, exports) { - /** - * Alignment pattern are fixed reference pattern in defined positions - * in a matrix symbology, which enables the decode software to re-synchronise - * the coordinate mapping of the image modules in the event of moderate amounts - * of distortion of the image. - * - * Alignment patterns are present only in QR Code symbols of version 2 or larger - * and their number depends on the symbol version. - */ - - var getSymbolSize = utils.getSymbolSize; - - /** - * Calculate the row/column coordinates of the center module of each alignment pattern - * for the specified QR Code version. - * - * The alignment patterns are positioned symmetrically on either side of the diagonal - * running from the top left corner of the symbol to the bottom right corner. - * - * Since positions are simmetrical only half of the coordinates are returned. - * Each item of the array will represent in turn the x and y coordinate. - * @see {@link getPositions} - * - * @param {Number} version QR Code version - * @return {Array} Array of coordinate - */ - exports.getRowColCoords = function getRowColCoords (version) { - if (version === 1) return [] - - var posCount = Math.floor(version / 7) + 2; - var size = getSymbolSize(version); - var intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2; - var positions = [size - 7]; // Last coord is always (size - 7) - - for (var i = 1; i < posCount - 1; i++) { - positions[i] = positions[i - 1] - intervals; - } - - positions.push(6); // First coord is always 6 - - return positions.reverse() - }; - - /** - * Returns an array containing the positions of each alignment pattern. - * Each array's element represent the center point of the pattern as (x, y) coordinates - * - * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords} - * and filtering out the items that overlaps with finder pattern - * - * @example - * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38. - * The alignment patterns, therefore, are to be centered on (row, column) - * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38). - * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns - * and are not therefore used for alignment patterns. - * - * var pos = getPositions(7) - * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]] - * - * @param {Number} version QR Code version - * @return {Array} Array of coordinates - */ - exports.getPositions = function getPositions (version) { - var coords = []; - var pos = exports.getRowColCoords(version); - var posLength = pos.length; - - for (var i = 0; i < posLength; i++) { - for (var j = 0; j < posLength; j++) { - // Skip if position is occupied by finder patterns - if ((i === 0 && j === 0) || // top-left - (i === 0 && j === posLength - 1) || // bottom-left - (i === posLength - 1 && j === 0)) { // top-right - continue - } - - coords.push([pos[i], pos[j]]); - } - } - - return coords - }; - }); - var alignmentPattern_1 = alignmentPattern.getRowColCoords; - var alignmentPattern_2 = alignmentPattern.getPositions; - - var getSymbolSize$1 = utils.getSymbolSize; - var FINDER_PATTERN_SIZE = 7; - - /** - * Returns an array containing the positions of each finder pattern. - * Each array's element represent the top-left point of the pattern as (x, y) coordinates - * - * @param {Number} version QR Code version - * @return {Array} Array of coordinates - */ - var getPositions = function getPositions (version) { - var size = getSymbolSize$1(version); - - return [ - // top-left - [0, 0], - // top-right - [size - FINDER_PATTERN_SIZE, 0], - // bottom-left - [0, size - FINDER_PATTERN_SIZE] - ] - }; - - var finderPattern = { - getPositions: getPositions - }; - - var maskPattern = createCommonjsModule(function (module, exports) { - /** - * Data mask pattern reference - * @type {Object} - */ - exports.Patterns = { - PATTERN000: 0, - PATTERN001: 1, - PATTERN010: 2, - PATTERN011: 3, - PATTERN100: 4, - PATTERN101: 5, - PATTERN110: 6, - PATTERN111: 7 - }; - - /** - * Weighted penalty scores for the undesirable features - * @type {Object} - */ - var PenaltyScores = { - N1: 3, - N2: 3, - N3: 40, - N4: 10 - }; - - /** - * Find adjacent modules in row/column with the same color - * and assign a penalty value. - * - * Points: N1 + i - * i is the amount by which the number of adjacent modules of the same color exceeds 5 - */ - exports.getPenaltyN1 = function getPenaltyN1 (data) { - var size = data.size; - var points = 0; - var sameCountCol = 0; - var sameCountRow = 0; - var lastCol = null; - var lastRow = null; - - for (var row = 0; row < size; row++) { - sameCountCol = sameCountRow = 0; - lastCol = lastRow = null; - - for (var col = 0; col < size; col++) { - var module = data.get(row, col); - if (module === lastCol) { - sameCountCol++; - } else { - if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5); - lastCol = module; - sameCountCol = 1; - } - - module = data.get(col, row); - if (module === lastRow) { - sameCountRow++; - } else { - if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5); - lastRow = module; - sameCountRow = 1; - } - } - - if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5); - if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5); - } - - return points - }; - - /** - * Find 2x2 blocks with the same color and assign a penalty value - * - * Points: N2 * (m - 1) * (n - 1) - */ - exports.getPenaltyN2 = function getPenaltyN2 (data) { - var size = data.size; - var points = 0; - - for (var row = 0; row < size - 1; row++) { - for (var col = 0; col < size - 1; col++) { - var last = data.get(row, col) + - data.get(row, col + 1) + - data.get(row + 1, col) + - data.get(row + 1, col + 1); - - if (last === 4 || last === 0) points++; - } - } - - return points * PenaltyScores.N2 - }; - - /** - * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column, - * preceded or followed by light area 4 modules wide - * - * Points: N3 * number of pattern found - */ - exports.getPenaltyN3 = function getPenaltyN3 (data) { - var size = data.size; - var points = 0; - var bitsCol = 0; - var bitsRow = 0; - - for (var row = 0; row < size; row++) { - bitsCol = bitsRow = 0; - for (var col = 0; col < size; col++) { - bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col); - if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++; - - bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row); - if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++; - } - } - - return points * PenaltyScores.N3 - }; - - /** - * Calculate proportion of dark modules in entire symbol - * - * Points: N4 * k - * - * k is the rating of the deviation of the proportion of dark modules - * in the symbol from 50% in steps of 5% - */ - exports.getPenaltyN4 = function getPenaltyN4 (data) { - var darkCount = 0; - var modulesCount = data.data.length; - - for (var i = 0; i < modulesCount; i++) darkCount += data.data[i]; - - var k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10); - - return k * PenaltyScores.N4 - }; - - /** - * Return mask value at given position - * - * @param {Number} maskPattern Pattern reference value - * @param {Number} i Row - * @param {Number} j Column - * @return {Boolean} Mask value - */ - function getMaskAt (maskPattern, i, j) { - switch (maskPattern) { - case exports.Patterns.PATTERN000: return (i + j) % 2 === 0 - case exports.Patterns.PATTERN001: return i % 2 === 0 - case exports.Patterns.PATTERN010: return j % 3 === 0 - case exports.Patterns.PATTERN011: return (i + j) % 3 === 0 - case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0 - case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0 - case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0 - case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0 - - default: throw new Error('bad maskPattern:' + maskPattern) - } - } - - /** - * Apply a mask pattern to a BitMatrix - * - * @param {Number} pattern Pattern reference number - * @param {BitMatrix} data BitMatrix data - */ - exports.applyMask = function applyMask (pattern, data) { - var size = data.size; - - for (var col = 0; col < size; col++) { - for (var row = 0; row < size; row++) { - if (data.isReserved(row, col)) continue - data.xor(row, col, getMaskAt(pattern, row, col)); - } - } - }; - - /** - * Returns the best mask pattern for data - * - * @param {BitMatrix} data - * @return {Number} Mask pattern reference number - */ - exports.getBestMask = function getBestMask (data, setupFormatFunc) { - var numPatterns = Object.keys(exports.Patterns).length; - var bestPattern = 0; - var lowerPenalty = Infinity; - - for (var p = 0; p < numPatterns; p++) { - setupFormatFunc(p); - exports.applyMask(p, data); - - // Calculate penalty - var penalty = - exports.getPenaltyN1(data) + - exports.getPenaltyN2(data) + - exports.getPenaltyN3(data) + - exports.getPenaltyN4(data); - - // Undo previously applied mask - exports.applyMask(p, data); - - if (penalty < lowerPenalty) { - lowerPenalty = penalty; - bestPattern = p; - } - } - - return bestPattern - }; - }); - var maskPattern_1 = maskPattern.Patterns; - var maskPattern_2 = maskPattern.getPenaltyN1; - var maskPattern_3 = maskPattern.getPenaltyN2; - var maskPattern_4 = maskPattern.getPenaltyN3; - var maskPattern_5 = maskPattern.getPenaltyN4; - var maskPattern_6 = maskPattern.applyMask; - var maskPattern_7 = maskPattern.getBestMask; - - var EC_BLOCKS_TABLE = [ - // L M Q H - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 2, 2, - 1, 2, 2, 4, - 1, 2, 4, 4, - 2, 4, 4, 4, - 2, 4, 6, 5, - 2, 4, 6, 6, - 2, 5, 8, 8, - 4, 5, 8, 8, - 4, 5, 8, 11, - 4, 8, 10, 11, - 4, 9, 12, 16, - 4, 9, 16, 16, - 6, 10, 12, 18, - 6, 10, 17, 16, - 6, 11, 16, 19, - 6, 13, 18, 21, - 7, 14, 21, 25, - 8, 16, 20, 25, - 8, 17, 23, 25, - 9, 17, 23, 34, - 9, 18, 25, 30, - 10, 20, 27, 32, - 12, 21, 29, 35, - 12, 23, 34, 37, - 12, 25, 34, 40, - 13, 26, 35, 42, - 14, 28, 38, 45, - 15, 29, 40, 48, - 16, 31, 43, 51, - 17, 33, 45, 54, - 18, 35, 48, 57, - 19, 37, 51, 60, - 19, 38, 53, 63, - 20, 40, 56, 66, - 21, 43, 59, 70, - 22, 45, 62, 74, - 24, 47, 65, 77, - 25, 49, 68, 81 - ]; - - var EC_CODEWORDS_TABLE = [ - // L M Q H - 7, 10, 13, 17, - 10, 16, 22, 28, - 15, 26, 36, 44, - 20, 36, 52, 64, - 26, 48, 72, 88, - 36, 64, 96, 112, - 40, 72, 108, 130, - 48, 88, 132, 156, - 60, 110, 160, 192, - 72, 130, 192, 224, - 80, 150, 224, 264, - 96, 176, 260, 308, - 104, 198, 288, 352, - 120, 216, 320, 384, - 132, 240, 360, 432, - 144, 280, 408, 480, - 168, 308, 448, 532, - 180, 338, 504, 588, - 196, 364, 546, 650, - 224, 416, 600, 700, - 224, 442, 644, 750, - 252, 476, 690, 816, - 270, 504, 750, 900, - 300, 560, 810, 960, - 312, 588, 870, 1050, - 336, 644, 952, 1110, - 360, 700, 1020, 1200, - 390, 728, 1050, 1260, - 420, 784, 1140, 1350, - 450, 812, 1200, 1440, - 480, 868, 1290, 1530, - 510, 924, 1350, 1620, - 540, 980, 1440, 1710, - 570, 1036, 1530, 1800, - 570, 1064, 1590, 1890, - 600, 1120, 1680, 1980, - 630, 1204, 1770, 2100, - 660, 1260, 1860, 2220, - 720, 1316, 1950, 2310, - 750, 1372, 2040, 2430 - ]; - - /** - * Returns the number of error correction block that the QR Code should contain - * for the specified version and error correction level. - * - * @param {Number} version QR Code version - * @param {Number} errorCorrectionLevel Error correction level - * @return {Number} Number of error correction blocks - */ - var getBlocksCount = function getBlocksCount (version, errorCorrectionLevel$1) { - switch (errorCorrectionLevel$1) { - case errorCorrectionLevel.L: - return EC_BLOCKS_TABLE[(version - 1) * 4 + 0] - case errorCorrectionLevel.M: - return EC_BLOCKS_TABLE[(version - 1) * 4 + 1] - case errorCorrectionLevel.Q: - return EC_BLOCKS_TABLE[(version - 1) * 4 + 2] - case errorCorrectionLevel.H: - return EC_BLOCKS_TABLE[(version - 1) * 4 + 3] - default: - return undefined - } - }; - - /** - * Returns the number of error correction codewords to use for the specified - * version and error correction level. - * - * @param {Number} version QR Code version - * @param {Number} errorCorrectionLevel Error correction level - * @return {Number} Number of error correction codewords - */ - var getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel$1) { - switch (errorCorrectionLevel$1) { - case errorCorrectionLevel.L: - return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0] - case errorCorrectionLevel.M: - return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1] - case errorCorrectionLevel.Q: - return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2] - case errorCorrectionLevel.H: - return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3] - default: - return undefined - } - }; - - var errorCorrectionCode = { - getBlocksCount: getBlocksCount, - getTotalCodewordsCount: getTotalCodewordsCount - }; - - var EXP_TABLE = new typedarrayBuffer(512); - var LOG_TABLE = new typedarrayBuffer(256) - - /** - * Precompute the log and anti-log tables for faster computation later - * - * For each possible value in the galois field 2^8, we will pre-compute - * the logarithm and anti-logarithm (exponential) of this value - * - * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields} - */ - ;(function initTables () { - var x = 1; - for (var i = 0; i < 255; i++) { - EXP_TABLE[i] = x; - LOG_TABLE[x] = i; - - x <<= 1; // multiply by 2 - - // The QR code specification says to use byte-wise modulo 100011101 arithmetic. - // This means that when a number is 256 or larger, it should be XORed with 0x11D. - if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256) - x ^= 0x11D; - } - } - - // Optimization: double the size of the anti-log table so that we don't need to mod 255 to - // stay inside the bounds (because we will mainly use this table for the multiplication of - // two GF numbers, no more). - // @see {@link mul} - for (i = 255; i < 512; i++) { - EXP_TABLE[i] = EXP_TABLE[i - 255]; - } - }()); - - /** - * Returns log value of n inside Galois Field - * - * @param {Number} n - * @return {Number} - */ - var log = function log (n) { - if (n < 1) throw new Error('log(' + n + ')') - return LOG_TABLE[n] - }; - - /** - * Returns anti-log value of n inside Galois Field - * - * @param {Number} n - * @return {Number} - */ - var exp = function exp (n) { - return EXP_TABLE[n] - }; - - /** - * Multiplies two number inside Galois Field - * - * @param {Number} x - * @param {Number} y - * @return {Number} - */ - var mul = function mul (x, y) { - if (x === 0 || y === 0) return 0 - - // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized - // @see {@link initTables} - return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]] - }; - - var galoisField = { - log: log, - exp: exp, - mul: mul - }; - - var polynomial = createCommonjsModule(function (module, exports) { - /** - * Multiplies two polynomials inside Galois Field - * - * @param {Buffer} p1 Polynomial - * @param {Buffer} p2 Polynomial - * @return {Buffer} Product of p1 and p2 - */ - exports.mul = function mul (p1, p2) { - var coeff = new typedarrayBuffer(p1.length + p2.length - 1); - coeff.fill(0); - - for (var i = 0; i < p1.length; i++) { - for (var j = 0; j < p2.length; j++) { - coeff[i + j] ^= galoisField.mul(p1[i], p2[j]); - } - } - - return coeff - }; - - /** - * Calculate the remainder of polynomials division - * - * @param {Buffer} divident Polynomial - * @param {Buffer} divisor Polynomial - * @return {Buffer} Remainder - */ - exports.mod = function mod (divident, divisor) { - var result = new typedarrayBuffer(divident); - - while ((result.length - divisor.length) >= 0) { - var coeff = result[0]; - - for (var i = 0; i < divisor.length; i++) { - result[i] ^= galoisField.mul(divisor[i], coeff); - } - - // remove all zeros from buffer head - var offset = 0; - while (offset < result.length && result[offset] === 0) offset++; - result = result.slice(offset); - } - - return result - }; - - /** - * Generate an irreducible generator polynomial of specified degree - * (used by Reed-Solomon encoder) - * - * @param {Number} degree Degree of the generator polynomial - * @return {Buffer} Buffer containing polynomial coefficients - */ - exports.generateECPolynomial = function generateECPolynomial (degree) { - var poly = new typedarrayBuffer([1]); - for (var i = 0; i < degree; i++) { - poly = exports.mul(poly, [1, galoisField.exp(i)]); - } - - return poly - }; - }); - var polynomial_1 = polynomial.mul; - var polynomial_2 = polynomial.mod; - var polynomial_3 = polynomial.generateECPolynomial; - - function ReedSolomonEncoder (degree) { - this.genPoly = undefined; - this.degree = degree; - - if (this.degree) this.initialize(this.degree); - } - - /** - * Initialize the encoder. - * The input param should correspond to the number of error correction codewords. - * - * @param {Number} degree - */ - ReedSolomonEncoder.prototype.initialize = function initialize (degree) { - // create an irreducible generator polynomial - this.degree = degree; - this.genPoly = polynomial.generateECPolynomial(this.degree); - }; - - /** - * Encodes a chunk of data - * - * @param {Buffer} data Buffer containing input data - * @return {Buffer} Buffer containing encoded data - */ - ReedSolomonEncoder.prototype.encode = function encode (data) { - if (!this.genPoly) { - throw new Error('Encoder not initialized') - } - - // Calculate EC for this data block - // extends data size to data+genPoly size - var pad = new typedarrayBuffer(this.degree); - pad.fill(0); - var paddedData = typedarrayBuffer.concat([data, pad], data.length + this.degree); - - // The error correction codewords are the remainder after dividing the data codewords - // by a generator polynomial - var remainder = polynomial.mod(paddedData, this.genPoly); - - // return EC data blocks (last n byte, where n is the degree of genPoly) - // If coefficients number in remainder are less than genPoly degree, - // pad with 0s to the left to reach the needed number of coefficients - var start = this.degree - remainder.length; - if (start > 0) { - var buff = new typedarrayBuffer(this.degree); - buff.fill(0); - remainder.copy(buff, start); - - return buff - } - - return remainder - }; - - var reedSolomonEncoder = ReedSolomonEncoder; - - var numeric = '[0-9]+'; - var alphanumeric = '[A-Z $%*+-./:]+'; - var kanji = '(?:[\u3000-\u303F]|[\u3040-\u309F]|[\u30A0-\u30FF]|' + - '[\uFF00-\uFFEF]|[\u4E00-\u9FAF]|[\u2605-\u2606]|[\u2190-\u2195]|\u203B|' + - '[\u2010\u2015\u2018\u2019\u2025\u2026\u201C\u201D\u2225\u2260]|' + - '[\u0391-\u0451]|[\u00A7\u00A8\u00B1\u00B4\u00D7\u00F7])+'; - var byte = '(?:(?![A-Z0-9 $%*+-./:]|' + kanji + ').)+'; - - var KANJI = new RegExp(kanji, 'g'); - var BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+-./:]+', 'g'); - var BYTE = new RegExp(byte, 'g'); - var NUMERIC = new RegExp(numeric, 'g'); - var ALPHANUMERIC = new RegExp(alphanumeric, 'g'); - - var TEST_KANJI = new RegExp('^' + kanji + '$'); - var TEST_NUMERIC = new RegExp('^' + numeric + '$'); - var TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+-./:]+$'); - - var testKanji = function testKanji (str) { - return TEST_KANJI.test(str) - }; - - var testNumeric = function testNumeric (str) { - return TEST_NUMERIC.test(str) - }; - - var testAlphanumeric = function testAlphanumeric (str) { - return TEST_ALPHANUMERIC.test(str) - }; - - var regex = { - KANJI: KANJI, - BYTE_KANJI: BYTE_KANJI, - BYTE: BYTE, - NUMERIC: NUMERIC, - ALPHANUMERIC: ALPHANUMERIC, - testKanji: testKanji, - testNumeric: testNumeric, - testAlphanumeric: testAlphanumeric - }; - - var mode = createCommonjsModule(function (module, exports) { - /** - * Numeric mode encodes data from the decimal digit set (0 - 9) - * (byte values 30HEX to 39HEX). - * Normally, 3 data characters are represented by 10 bits. - * - * @type {Object} - */ - exports.NUMERIC = { - id: 'Numeric', - bit: 1 << 0, - ccBits: [10, 12, 14] - }; - - /** - * Alphanumeric mode encodes data from a set of 45 characters, - * i.e. 10 numeric digits (0 - 9), - * 26 alphabetic characters (A - Z), - * and 9 symbols (SP, $, %, *, +, -, ., /, :). - * Normally, two input characters are represented by 11 bits. - * - * @type {Object} - */ - exports.ALPHANUMERIC = { - id: 'Alphanumeric', - bit: 1 << 1, - ccBits: [9, 11, 13] - }; - - /** - * In byte mode, data is encoded at 8 bits per character. - * - * @type {Object} - */ - exports.BYTE = { - id: 'Byte', - bit: 1 << 2, - ccBits: [8, 16, 16] - }; - - /** - * The Kanji mode efficiently encodes Kanji characters in accordance with - * the Shift JIS system based on JIS X 0208. - * The Shift JIS values are shifted from the JIS X 0208 values. - * JIS X 0208 gives details of the shift coded representation. - * Each two-byte character value is compacted to a 13-bit binary codeword. - * - * @type {Object} - */ - exports.KANJI = { - id: 'Kanji', - bit: 1 << 3, - ccBits: [8, 10, 12] - }; - - /** - * Mixed mode will contain a sequences of data in a combination of any of - * the modes described above - * - * @type {Object} - */ - exports.MIXED = { - bit: -1 - }; - - /** - * Returns the number of bits needed to store the data length - * according to QR Code specifications. - * - * @param {Mode} mode Data mode - * @param {Number} version QR Code version - * @return {Number} Number of bits - */ - exports.getCharCountIndicator = function getCharCountIndicator (mode, version$1) { - if (!mode.ccBits) throw new Error('Invalid mode: ' + mode) - - if (!version.isValid(version$1)) { - throw new Error('Invalid version: ' + version$1) - } - - if (version$1 >= 1 && version$1 < 10) return mode.ccBits[0] - else if (version$1 < 27) return mode.ccBits[1] - return mode.ccBits[2] - }; - - /** - * Returns the most efficient mode to store the specified data - * - * @param {String} dataStr Input data string - * @return {Mode} Best mode - */ - exports.getBestModeForData = function getBestModeForData (dataStr) { - if (regex.testNumeric(dataStr)) return exports.NUMERIC - else if (regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC - else if (regex.testKanji(dataStr)) return exports.KANJI - else return exports.BYTE - }; - - /** - * Return mode name as string - * - * @param {Mode} mode Mode object - * @returns {String} Mode name - */ - exports.toString = function toString (mode) { - if (mode && mode.id) return mode.id - throw new Error('Invalid mode') - }; - - /** - * Check if input param is a valid mode object - * - * @param {Mode} mode Mode object - * @returns {Boolean} True if valid mode, false otherwise - */ - exports.isValid = function isValid (mode) { - return mode && mode.bit && mode.ccBits - }; - - /** - * Get mode object from its name - * - * @param {String} string Mode name - * @returns {Mode} Mode object - */ - function fromString (string) { - if (typeof string !== 'string') { - throw new Error('Param is not a string') - } - - var lcStr = string.toLowerCase(); - - switch (lcStr) { - case 'numeric': - return exports.NUMERIC - case 'alphanumeric': - return exports.ALPHANUMERIC - case 'kanji': - return exports.KANJI - case 'byte': - return exports.BYTE - default: - throw new Error('Unknown mode: ' + string) - } - } - - /** - * Returns mode from a value. - * If value is not a valid mode, returns defaultValue - * - * @param {Mode|String} value Encoding mode - * @param {Mode} defaultValue Fallback value - * @return {Mode} Encoding mode - */ - exports.from = function from (value, defaultValue) { - if (exports.isValid(value)) { - return value - } - - try { - return fromString(value) - } catch (e) { - return defaultValue - } - }; - }); - var mode_1 = mode.NUMERIC; - var mode_2 = mode.ALPHANUMERIC; - var mode_3 = mode.BYTE; - var mode_4 = mode.KANJI; - var mode_5 = mode.MIXED; - var mode_6 = mode.getCharCountIndicator; - var mode_7 = mode.getBestModeForData; - var mode_8 = mode.isValid; - - var version = createCommonjsModule(function (module, exports) { - // Generator polynomial used to encode version information - var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0); - var G18_BCH = utils.getBCHDigit(G18); - - function getBestVersionForDataLength (mode, length, errorCorrectionLevel) { - for (var currentVersion = 1; currentVersion <= 40; currentVersion++) { - if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) { - return currentVersion - } - } - - return undefined - } - - function getReservedBitsCount (mode$1, version) { - // Character count indicator + mode indicator bits - return mode.getCharCountIndicator(mode$1, version) + 4 - } - - function getTotalBitsFromDataArray (segments, version) { - var totalBits = 0; - - segments.forEach(function (data) { - var reservedBits = getReservedBitsCount(data.mode, version); - totalBits += reservedBits + data.getBitsLength(); - }); - - return totalBits - } - - function getBestVersionForMixedData (segments, errorCorrectionLevel) { - for (var currentVersion = 1; currentVersion <= 40; currentVersion++) { - var length = getTotalBitsFromDataArray(segments, currentVersion); - if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode.MIXED)) { - return currentVersion - } - } - - return undefined - } - - /** - * Check if QR Code version is valid - * - * @param {Number} version QR Code version - * @return {Boolean} true if valid version, false otherwise - */ - exports.isValid = function isValid (version) { - return !isNaN(version) && version >= 1 && version <= 40 - }; - - /** - * Returns version number from a value. - * If value is not a valid version, returns defaultValue - * - * @param {Number|String} value QR Code version - * @param {Number} defaultValue Fallback value - * @return {Number} QR Code version number - */ - exports.from = function from (value, defaultValue) { - if (exports.isValid(value)) { - return parseInt(value, 10) - } - - return defaultValue - }; - - /** - * Returns how much data can be stored with the specified QR code version - * and error correction level - * - * @param {Number} version QR Code version (1-40) - * @param {Number} errorCorrectionLevel Error correction level - * @param {Mode} mode Data mode - * @return {Number} Quantity of storable data - */ - exports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode$1) { - if (!exports.isValid(version)) { - throw new Error('Invalid QR Code version') - } - - // Use Byte mode as default - if (typeof mode$1 === 'undefined') mode$1 = mode.BYTE; - - // Total codewords for this QR code version (Data + Error correction) - var totalCodewords = utils.getSymbolTotalCodewords(version); - - // Total number of error correction codewords - var ecTotalCodewords = errorCorrectionCode.getTotalCodewordsCount(version, errorCorrectionLevel); - - // Total number of data codewords - var dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8; - - if (mode$1 === mode.MIXED) return dataTotalCodewordsBits - - var usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode$1, version); - - // Return max number of storable codewords - switch (mode$1) { - case mode.NUMERIC: - return Math.floor((usableBits / 10) * 3) - - case mode.ALPHANUMERIC: - return Math.floor((usableBits / 11) * 2) - - case mode.KANJI: - return Math.floor(usableBits / 13) - - case mode.BYTE: - default: - return Math.floor(usableBits / 8) - } - }; - - /** - * Returns the minimum version needed to contain the amount of data - * - * @param {Segment} data Segment of data - * @param {Number} [errorCorrectionLevel=H] Error correction level - * @param {Mode} mode Data mode - * @return {Number} QR Code version - */ - exports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel$1) { - var seg; - - var ecl = errorCorrectionLevel.from(errorCorrectionLevel$1, errorCorrectionLevel.M); - - if (isarray(data)) { - if (data.length > 1) { - return getBestVersionForMixedData(data, ecl) - } - - if (data.length === 0) { - return 1 - } - - seg = data[0]; - } else { - seg = data; - } - - return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl) - }; - - /** - * Returns version information with relative error correction bits - * - * The version information is included in QR Code symbols of version 7 or larger. - * It consists of an 18-bit sequence containing 6 data bits, - * with 12 error correction bits calculated using the (18, 6) Golay code. - * - * @param {Number} version QR Code version - * @return {Number} Encoded version info bits - */ - exports.getEncodedBits = function getEncodedBits (version) { - if (!exports.isValid(version) || version < 7) { - throw new Error('Invalid QR Code version') - } - - var d = version << 12; - - while (utils.getBCHDigit(d) - G18_BCH >= 0) { - d ^= (G18 << (utils.getBCHDigit(d) - G18_BCH)); - } - - return (version << 12) | d - }; - }); - var version_1 = version.isValid; - var version_2 = version.getCapacity; - var version_3 = version.getBestVersionForData; - var version_4 = version.getEncodedBits; - - var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0); - var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1); - var G15_BCH = utils.getBCHDigit(G15); - - /** - * Returns format information with relative error correction bits - * - * The format information is a 15-bit sequence containing 5 data bits, - * with 10 error correction bits calculated using the (15, 5) BCH code. - * - * @param {Number} errorCorrectionLevel Error correction level - * @param {Number} mask Mask pattern - * @return {Number} Encoded format information bits - */ - var getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) { - var data = ((errorCorrectionLevel.bit << 3) | mask); - var d = data << 10; - - while (utils.getBCHDigit(d) - G15_BCH >= 0) { - d ^= (G15 << (utils.getBCHDigit(d) - G15_BCH)); - } - - // xor final data with mask pattern in order to ensure that - // no combination of Error Correction Level and data mask pattern - // will result in an all-zero data string - return ((data << 10) | d) ^ G15_MASK - }; - - var formatInfo = { - getEncodedBits: getEncodedBits - }; - - function NumericData (data) { - this.mode = mode.NUMERIC; - this.data = data.toString(); - } - - NumericData.getBitsLength = function getBitsLength (length) { - return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0) - }; - - NumericData.prototype.getLength = function getLength () { - return this.data.length - }; - - NumericData.prototype.getBitsLength = function getBitsLength () { - return NumericData.getBitsLength(this.data.length) - }; - - NumericData.prototype.write = function write (bitBuffer) { - var i, group, value; - - // The input data string is divided into groups of three digits, - // and each group is converted to its 10-bit binary equivalent. - for (i = 0; i + 3 <= this.data.length; i += 3) { - group = this.data.substr(i, 3); - value = parseInt(group, 10); - - bitBuffer.put(value, 10); - } - - // If the number of input digits is not an exact multiple of three, - // the final one or two digits are converted to 4 or 7 bits respectively. - var remainingNum = this.data.length - i; - if (remainingNum > 0) { - group = this.data.substr(i); - value = parseInt(group, 10); - - bitBuffer.put(value, remainingNum * 3 + 1); - } - }; - - var numericData = NumericData; - - /** - * Array of characters available in alphanumeric mode - * - * As per QR Code specification, to each character - * is assigned a value from 0 to 44 which in this case coincides - * with the array index - * - * @type {Array} - */ - var ALPHA_NUM_CHARS = [ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - ' ', '$', '%', '*', '+', '-', '.', '/', ':' - ]; - - function AlphanumericData (data) { - this.mode = mode.ALPHANUMERIC; - this.data = data; - } - - AlphanumericData.getBitsLength = function getBitsLength (length) { - return 11 * Math.floor(length / 2) + 6 * (length % 2) - }; - - AlphanumericData.prototype.getLength = function getLength () { - return this.data.length - }; - - AlphanumericData.prototype.getBitsLength = function getBitsLength () { - return AlphanumericData.getBitsLength(this.data.length) - }; - - AlphanumericData.prototype.write = function write (bitBuffer) { - var i; - - // Input data characters are divided into groups of two characters - // and encoded as 11-bit binary codes. - for (i = 0; i + 2 <= this.data.length; i += 2) { - // The character value of the first character is multiplied by 45 - var value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45; - - // The character value of the second digit is added to the product - value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]); - - // The sum is then stored as 11-bit binary number - bitBuffer.put(value, 11); - } - - // If the number of input data characters is not a multiple of two, - // the character value of the final character is encoded as a 6-bit binary number. - if (this.data.length % 2) { - bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6); - } - }; - - var alphanumericData = AlphanumericData; - - function ByteData (data) { - this.mode = mode.BYTE; - this.data = new typedarrayBuffer(data); - } - - ByteData.getBitsLength = function getBitsLength (length) { - return length * 8 - }; - - ByteData.prototype.getLength = function getLength () { - return this.data.length - }; - - ByteData.prototype.getBitsLength = function getBitsLength () { - return ByteData.getBitsLength(this.data.length) - }; - - ByteData.prototype.write = function (bitBuffer) { - for (var i = 0, l = this.data.length; i < l; i++) { - bitBuffer.put(this.data[i], 8); - } - }; - - var byteData = ByteData; - - function KanjiData (data) { - this.mode = mode.KANJI; - this.data = data; - } - - KanjiData.getBitsLength = function getBitsLength (length) { - return length * 13 - }; - - KanjiData.prototype.getLength = function getLength () { - return this.data.length - }; - - KanjiData.prototype.getBitsLength = function getBitsLength () { - return KanjiData.getBitsLength(this.data.length) - }; - - KanjiData.prototype.write = function (bitBuffer) { - var i; - - // In the Shift JIS system, Kanji characters are represented by a two byte combination. - // These byte values are shifted from the JIS X 0208 values. - // JIS X 0208 gives details of the shift coded representation. - for (i = 0; i < this.data.length; i++) { - var value = utils.toSJIS(this.data[i]); - - // For characters with Shift JIS values from 0x8140 to 0x9FFC: - if (value >= 0x8140 && value <= 0x9FFC) { - // Subtract 0x8140 from Shift JIS value - value -= 0x8140; - - // For characters with Shift JIS values from 0xE040 to 0xEBBF - } else if (value >= 0xE040 && value <= 0xEBBF) { - // Subtract 0xC140 from Shift JIS value - value -= 0xC140; - } else { - throw new Error( - 'Invalid SJIS character: ' + this.data[i] + '\n' + - 'Make sure your charset is UTF-8') - } - - // Multiply most significant byte of result by 0xC0 - // and add least significant byte to product - value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff); - - // Convert result to a 13-bit binary string - bitBuffer.put(value, 13); - } - }; - - var kanjiData = KanjiData; - - var dijkstra_1 = createCommonjsModule(function (module) { - - /****************************************************************************** - * Created 2008-08-19. - * - * Dijkstra path-finding functions. Adapted from the Dijkstar Python project. - * - * Copyright (C) 2008 - * Wyatt Baldwin - * All rights reserved - * - * Licensed under the MIT license. - * - * http://www.opensource.org/licenses/mit-license.php - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - *****************************************************************************/ - var dijkstra = { - single_source_shortest_paths: function(graph, s, d) { - // Predecessor map for each node that has been encountered. - // node ID => predecessor node ID - var predecessors = {}; - - // Costs of shortest paths from s to all nodes encountered. - // node ID => cost - var costs = {}; - costs[s] = 0; - - // Costs of shortest paths from s to all nodes encountered; differs from - // `costs` in that it provides easy access to the node that currently has - // the known shortest path from s. - // XXX: Do we actually need both `costs` and `open`? - var open = dijkstra.PriorityQueue.make(); - open.push(s, 0); - - var closest, - u, v, - cost_of_s_to_u, - adjacent_nodes, - cost_of_e, - cost_of_s_to_u_plus_cost_of_e, - cost_of_s_to_v, - first_visit; - while (!open.empty()) { - // In the nodes remaining in graph that have a known cost from s, - // find the node, u, that currently has the shortest path from s. - closest = open.pop(); - u = closest.value; - cost_of_s_to_u = closest.cost; - - // Get nodes adjacent to u... - adjacent_nodes = graph[u] || {}; - - // ...and explore the edges that connect u to those nodes, updating - // the cost of the shortest paths to any or all of those nodes as - // necessary. v is the node across the current edge from u. - for (v in adjacent_nodes) { - if (adjacent_nodes.hasOwnProperty(v)) { - // Get the cost of the edge running from u to v. - cost_of_e = adjacent_nodes[v]; - - // Cost of s to u plus the cost of u to v across e--this is *a* - // cost from s to v that may or may not be less than the current - // known cost to v. - cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e; - - // If we haven't visited v yet OR if the current known cost from s to - // v is greater than the new cost we just found (cost of s to u plus - // cost of u to v across e), update v's cost in the cost list and - // update v's predecessor in the predecessor list (it's now u). - cost_of_s_to_v = costs[v]; - first_visit = (typeof costs[v] === 'undefined'); - if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) { - costs[v] = cost_of_s_to_u_plus_cost_of_e; - open.push(v, cost_of_s_to_u_plus_cost_of_e); - predecessors[v] = u; - } - } - } - } - - if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') { - var msg = ['Could not find a path from ', s, ' to ', d, '.'].join(''); - throw new Error(msg); - } - - return predecessors; - }, - - extract_shortest_path_from_predecessor_list: function(predecessors, d) { - var nodes = []; - var u = d; - var predecessor; - while (u) { - nodes.push(u); - predecessor = predecessors[u]; - u = predecessors[u]; - } - nodes.reverse(); - return nodes; - }, - - find_path: function(graph, s, d) { - var predecessors = dijkstra.single_source_shortest_paths(graph, s, d); - return dijkstra.extract_shortest_path_from_predecessor_list( - predecessors, d); - }, - - /** - * A very naive priority queue implementation. - */ - PriorityQueue: { - make: function (opts) { - var T = dijkstra.PriorityQueue, - t = {}, - key; - opts = opts || {}; - for (key in T) { - if (T.hasOwnProperty(key)) { - t[key] = T[key]; - } - } - t.queue = []; - t.sorter = opts.sorter || T.default_sorter; - return t; - }, - - default_sorter: function (a, b) { - return a.cost - b.cost; - }, - - /** - * Add a new item to the queue and ensure the highest priority element - * is at the front of the queue. - */ - push: function (value, cost) { - var item = {value: value, cost: cost}; - this.queue.push(item); - this.queue.sort(this.sorter); - }, - - /** - * Return the highest priority element in the queue. - */ - pop: function () { - return this.queue.shift(); - }, - - empty: function () { - return this.queue.length === 0; - } - } - }; - - - // node.js module exports - { - module.exports = dijkstra; - } - }); - - var segments = createCommonjsModule(function (module, exports) { - /** - * Returns UTF8 byte length - * - * @param {String} str Input string - * @return {Number} Number of byte - */ - function getStringByteLength (str) { - return unescape(encodeURIComponent(str)).length - } - - /** - * Get a list of segments of the specified mode - * from a string - * - * @param {Mode} mode Segment mode - * @param {String} str String to process - * @return {Array} Array of object with segments data - */ - function getSegments (regex, mode, str) { - var segments = []; - var result; - - while ((result = regex.exec(str)) !== null) { - segments.push({ - data: result[0], - index: result.index, - mode: mode, - length: result[0].length - }); - } - - return segments - } - - /** - * Extracts a series of segments with the appropriate - * modes from a string - * - * @param {String} dataStr Input string - * @return {Array} Array of object with segments data - */ - function getSegmentsFromString (dataStr) { - var numSegs = getSegments(regex.NUMERIC, mode.NUMERIC, dataStr); - var alphaNumSegs = getSegments(regex.ALPHANUMERIC, mode.ALPHANUMERIC, dataStr); - var byteSegs; - var kanjiSegs; - - if (utils.isKanjiModeEnabled()) { - byteSegs = getSegments(regex.BYTE, mode.BYTE, dataStr); - kanjiSegs = getSegments(regex.KANJI, mode.KANJI, dataStr); - } else { - byteSegs = getSegments(regex.BYTE_KANJI, mode.BYTE, dataStr); - kanjiSegs = []; - } - - var segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs); - - return segs - .sort(function (s1, s2) { - return s1.index - s2.index - }) - .map(function (obj) { - return { - data: obj.data, - mode: obj.mode, - length: obj.length - } - }) - } - - /** - * Returns how many bits are needed to encode a string of - * specified length with the specified mode - * - * @param {Number} length String length - * @param {Mode} mode Segment mode - * @return {Number} Bit length - */ - function getSegmentBitsLength (length, mode$1) { - switch (mode$1) { - case mode.NUMERIC: - return numericData.getBitsLength(length) - case mode.ALPHANUMERIC: - return alphanumericData.getBitsLength(length) - case mode.KANJI: - return kanjiData.getBitsLength(length) - case mode.BYTE: - return byteData.getBitsLength(length) - } - } - - /** - * Merges adjacent segments which have the same mode - * - * @param {Array} segs Array of object with segments data - * @return {Array} Array of object with segments data - */ - function mergeSegments (segs) { - return segs.reduce(function (acc, curr) { - var prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null; - if (prevSeg && prevSeg.mode === curr.mode) { - acc[acc.length - 1].data += curr.data; - return acc - } - - acc.push(curr); - return acc - }, []) - } - - /** - * Generates a list of all possible nodes combination which - * will be used to build a segments graph. - * - * Nodes are divided by groups. Each group will contain a list of all the modes - * in which is possible to encode the given text. - * - * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte. - * The group for '12345' will contain then 3 objects, one for each - * possible encoding mode. - * - * Each node represents a possible segment. - * - * @param {Array} segs Array of object with segments data - * @return {Array} Array of object with segments data - */ - function buildNodes (segs) { - var nodes = []; - for (var i = 0; i < segs.length; i++) { - var seg = segs[i]; - - switch (seg.mode) { - case mode.NUMERIC: - nodes.push([seg, - { data: seg.data, mode: mode.ALPHANUMERIC, length: seg.length }, - { data: seg.data, mode: mode.BYTE, length: seg.length } - ]); - break - case mode.ALPHANUMERIC: - nodes.push([seg, - { data: seg.data, mode: mode.BYTE, length: seg.length } - ]); - break - case mode.KANJI: - nodes.push([seg, - { data: seg.data, mode: mode.BYTE, length: getStringByteLength(seg.data) } - ]); - break - case mode.BYTE: - nodes.push([ - { data: seg.data, mode: mode.BYTE, length: getStringByteLength(seg.data) } - ]); - } - } - - return nodes - } - - /** - * Builds a graph from a list of nodes. - * All segments in each node group will be connected with all the segments of - * the next group and so on. - * - * At each connection will be assigned a weight depending on the - * segment's byte length. - * - * @param {Array} nodes Array of object with segments data - * @param {Number} version QR Code version - * @return {Object} Graph of all possible segments - */ - function buildGraph (nodes, version) { - var table = {}; - var graph = {'start': {}}; - var prevNodeIds = ['start']; - - for (var i = 0; i < nodes.length; i++) { - var nodeGroup = nodes[i]; - var currentNodeIds = []; - - for (var j = 0; j < nodeGroup.length; j++) { - var node = nodeGroup[j]; - var key = '' + i + j; - - currentNodeIds.push(key); - table[key] = { node: node, lastCount: 0 }; - graph[key] = {}; - - for (var n = 0; n < prevNodeIds.length; n++) { - var prevNodeId = prevNodeIds[n]; - - if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) { - graph[prevNodeId][key] = - getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - - getSegmentBitsLength(table[prevNodeId].lastCount, node.mode); - - table[prevNodeId].lastCount += node.length; - } else { - if (table[prevNodeId]) table[prevNodeId].lastCount = node.length; - - graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + - 4 + mode.getCharCountIndicator(node.mode, version); // switch cost - } - } - } - - prevNodeIds = currentNodeIds; - } - - for (n = 0; n < prevNodeIds.length; n++) { - graph[prevNodeIds[n]]['end'] = 0; - } - - return { map: graph, table: table } - } - - /** - * Builds a segment from a specified data and mode. - * If a mode is not specified, the more suitable will be used. - * - * @param {String} data Input data - * @param {Mode | String} modesHint Data mode - * @return {Segment} Segment - */ - function buildSingleSegment (data, modesHint) { - var mode$1; - var bestMode = mode.getBestModeForData(data); - - mode$1 = mode.from(modesHint, bestMode); - - // Make sure data can be encoded - if (mode$1 !== mode.BYTE && mode$1.bit < bestMode.bit) { - throw new Error('"' + data + '"' + - ' cannot be encoded with mode ' + mode.toString(mode$1) + - '.\n Suggested mode is: ' + mode.toString(bestMode)) - } - - // Use Mode.BYTE if Kanji support is disabled - if (mode$1 === mode.KANJI && !utils.isKanjiModeEnabled()) { - mode$1 = mode.BYTE; - } - - switch (mode$1) { - case mode.NUMERIC: - return new numericData(data) - - case mode.ALPHANUMERIC: - return new alphanumericData(data) - - case mode.KANJI: - return new kanjiData(data) - - case mode.BYTE: - return new byteData(data) - } - } - - /** - * Builds a list of segments from an array. - * Array can contain Strings or Objects with segment's info. - * - * For each item which is a string, will be generated a segment with the given - * string and the more appropriate encoding mode. - * - * For each item which is an object, will be generated a segment with the given - * data and mode. - * Objects must contain at least the property "data". - * If property "mode" is not present, the more suitable mode will be used. - * - * @param {Array} array Array of objects with segments data - * @return {Array} Array of Segments - */ - exports.fromArray = function fromArray (array) { - return array.reduce(function (acc, seg) { - if (typeof seg === 'string') { - acc.push(buildSingleSegment(seg, null)); - } else if (seg.data) { - acc.push(buildSingleSegment(seg.data, seg.mode)); - } - - return acc - }, []) - }; - - /** - * Builds an optimized sequence of segments from a string, - * which will produce the shortest possible bitstream. - * - * @param {String} data Input string - * @param {Number} version QR Code version - * @return {Array} Array of segments - */ - exports.fromString = function fromString (data, version) { - var segs = getSegmentsFromString(data, utils.isKanjiModeEnabled()); - - var nodes = buildNodes(segs); - var graph = buildGraph(nodes, version); - var path = dijkstra_1.find_path(graph.map, 'start', 'end'); - - var optimizedSegs = []; - for (var i = 1; i < path.length - 1; i++) { - optimizedSegs.push(graph.table[path[i]].node); - } - - return exports.fromArray(mergeSegments(optimizedSegs)) - }; - - /** - * Splits a string in various segments with the modes which - * best represent their content. - * The produced segments are far from being optimized. - * The output of this function is only used to estimate a QR Code version - * which may contain the data. - * - * @param {string} data Input string - * @return {Array} Array of segments - */ - exports.rawSplit = function rawSplit (data) { - return exports.fromArray( - getSegmentsFromString(data, utils.isKanjiModeEnabled()) - ) - }; - }); - var segments_1 = segments.fromArray; - var segments_2 = segments.fromString; - var segments_3 = segments.rawSplit; - - /** - * QRCode for JavaScript - * - * modified by Ryan Day for nodejs support - * Copyright (c) 2011 Ryan Day - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - //--------------------------------------------------------------------- - // QRCode for JavaScript - // - // Copyright (c) 2009 Kazuhiko Arase - // - // URL: http://www.d-project.com/ - // - // Licensed under the MIT license: - // http://www.opensource.org/licenses/mit-license.php - // - // The word "QR Code" is registered trademark of - // DENSO WAVE INCORPORATED - // http://www.denso-wave.com/qrcode/faqpatent-e.html - // - //--------------------------------------------------------------------- - */ - - /** - * Add finder patterns bits to matrix - * - * @param {BitMatrix} matrix Modules matrix - * @param {Number} version QR Code version - */ - function setupFinderPattern (matrix, version) { - var size = matrix.size; - var pos = finderPattern.getPositions(version); - - for (var i = 0; i < pos.length; i++) { - var row = pos[i][0]; - var col = pos[i][1]; - - for (var r = -1; r <= 7; r++) { - if (row + r <= -1 || size <= row + r) continue - - for (var c = -1; c <= 7; c++) { - if (col + c <= -1 || size <= col + c) continue - - if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) || - (c >= 0 && c <= 6 && (r === 0 || r === 6)) || - (r >= 2 && r <= 4 && c >= 2 && c <= 4)) { - matrix.set(row + r, col + c, true, true); - } else { - matrix.set(row + r, col + c, false, true); - } - } - } - } - } - - /** - * Add timing pattern bits to matrix - * - * Note: this function must be called before {@link setupAlignmentPattern} - * - * @param {BitMatrix} matrix Modules matrix - */ - function setupTimingPattern (matrix) { - var size = matrix.size; - - for (var r = 8; r < size - 8; r++) { - var value = r % 2 === 0; - matrix.set(r, 6, value, true); - matrix.set(6, r, value, true); - } - } - - /** - * Add alignment patterns bits to matrix - * - * Note: this function must be called after {@link setupTimingPattern} - * - * @param {BitMatrix} matrix Modules matrix - * @param {Number} version QR Code version - */ - function setupAlignmentPattern (matrix, version) { - var pos = alignmentPattern.getPositions(version); - - for (var i = 0; i < pos.length; i++) { - var row = pos[i][0]; - var col = pos[i][1]; - - for (var r = -2; r <= 2; r++) { - for (var c = -2; c <= 2; c++) { - if (r === -2 || r === 2 || c === -2 || c === 2 || - (r === 0 && c === 0)) { - matrix.set(row + r, col + c, true, true); - } else { - matrix.set(row + r, col + c, false, true); - } - } - } - } - } - - /** - * Add version info bits to matrix - * - * @param {BitMatrix} matrix Modules matrix - * @param {Number} version QR Code version - */ - function setupVersionInfo (matrix, version$1) { - var size = matrix.size; - var bits = version.getEncodedBits(version$1); - var row, col, mod; - - for (var i = 0; i < 18; i++) { - row = Math.floor(i / 3); - col = i % 3 + size - 8 - 3; - mod = ((bits >> i) & 1) === 1; - - matrix.set(row, col, mod, true); - matrix.set(col, row, mod, true); - } - } - - /** - * Add format info bits to matrix - * - * @param {BitMatrix} matrix Modules matrix - * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level - * @param {Number} maskPattern Mask pattern reference value - */ - function setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) { - var size = matrix.size; - var bits = formatInfo.getEncodedBits(errorCorrectionLevel, maskPattern); - var i, mod; - - for (i = 0; i < 15; i++) { - mod = ((bits >> i) & 1) === 1; - - // vertical - if (i < 6) { - matrix.set(i, 8, mod, true); - } else if (i < 8) { - matrix.set(i + 1, 8, mod, true); - } else { - matrix.set(size - 15 + i, 8, mod, true); - } - - // horizontal - if (i < 8) { - matrix.set(8, size - i - 1, mod, true); - } else if (i < 9) { - matrix.set(8, 15 - i - 1 + 1, mod, true); - } else { - matrix.set(8, 15 - i - 1, mod, true); - } - } - - // fixed module - matrix.set(size - 8, 8, 1, true); - } - - /** - * Add encoded data bits to matrix - * - * @param {BitMatrix} matrix Modules matrix - * @param {Buffer} data Data codewords - */ - function setupData (matrix, data) { - var size = matrix.size; - var inc = -1; - var row = size - 1; - var bitIndex = 7; - var byteIndex = 0; - - for (var col = size - 1; col > 0; col -= 2) { - if (col === 6) col--; - - while (true) { - for (var c = 0; c < 2; c++) { - if (!matrix.isReserved(row, col - c)) { - var dark = false; - - if (byteIndex < data.length) { - dark = (((data[byteIndex] >>> bitIndex) & 1) === 1); - } - - matrix.set(row, col - c, dark); - bitIndex--; - - if (bitIndex === -1) { - byteIndex++; - bitIndex = 7; - } - } - } - - row += inc; - - if (row < 0 || size <= row) { - row -= inc; - inc = -inc; - break - } - } - } - } - - /** - * Create encoded codewords from data input - * - * @param {Number} version QR Code version - * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level - * @param {ByteData} data Data input - * @return {Buffer} Buffer containing encoded codewords - */ - function createData (version, errorCorrectionLevel, segments) { - // Prepare data buffer - var buffer = new bitBuffer(); - - segments.forEach(function (data) { - // prefix data with mode indicator (4 bits) - buffer.put(data.mode.bit, 4); - - // Prefix data with character count indicator. - // The character count indicator is a string of bits that represents the - // number of characters that are being encoded. - // The character count indicator must be placed after the mode indicator - // and must be a certain number of bits long, depending on the QR version - // and data mode - // @see {@link Mode.getCharCountIndicator}. - buffer.put(data.getLength(), mode.getCharCountIndicator(data.mode, version)); - - // add binary data sequence to buffer - data.write(buffer); - }); - - // Calculate required number of bits - var totalCodewords = utils.getSymbolTotalCodewords(version); - var ecTotalCodewords = errorCorrectionCode.getTotalCodewordsCount(version, errorCorrectionLevel); - var dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8; - - // Add a terminator. - // If the bit string is shorter than the total number of required bits, - // a terminator of up to four 0s must be added to the right side of the string. - // If the bit string is more than four bits shorter than the required number of bits, - // add four 0s to the end. - if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) { - buffer.put(0, 4); - } - - // If the bit string is fewer than four bits shorter, add only the number of 0s that - // are needed to reach the required number of bits. - - // After adding the terminator, if the number of bits in the string is not a multiple of 8, - // pad the string on the right with 0s to make the string's length a multiple of 8. - while (buffer.getLengthInBits() % 8 !== 0) { - buffer.putBit(0); - } - - // Add pad bytes if the string is still shorter than the total number of required bits. - // Extend the buffer to fill the data capacity of the symbol corresponding to - // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC) - // and 00010001 (0x11) alternately. - var remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8; - for (var i = 0; i < remainingByte; i++) { - buffer.put(i % 2 ? 0x11 : 0xEC, 8); - } - - return createCodewords(buffer, version, errorCorrectionLevel) - } - - /** - * Encode input data with Reed-Solomon and return codewords with - * relative error correction bits - * - * @param {BitBuffer} bitBuffer Data to encode - * @param {Number} version QR Code version - * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level - * @return {Buffer} Buffer containing encoded codewords - */ - function createCodewords (bitBuffer, version, errorCorrectionLevel) { - // Total codewords for this QR code version (Data + Error correction) - var totalCodewords = utils.getSymbolTotalCodewords(version); - - // Total number of error correction codewords - var ecTotalCodewords = errorCorrectionCode.getTotalCodewordsCount(version, errorCorrectionLevel); - - // Total number of data codewords - var dataTotalCodewords = totalCodewords - ecTotalCodewords; - - // Total number of blocks - var ecTotalBlocks = errorCorrectionCode.getBlocksCount(version, errorCorrectionLevel); - - // Calculate how many blocks each group should contain - var blocksInGroup2 = totalCodewords % ecTotalBlocks; - var blocksInGroup1 = ecTotalBlocks - blocksInGroup2; - - var totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks); - - var dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks); - var dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1; - - // Number of EC codewords is the same for both groups - var ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1; - - // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount - var rs = new reedSolomonEncoder(ecCount); - - var offset = 0; - var dcData = new Array(ecTotalBlocks); - var ecData = new Array(ecTotalBlocks); - var maxDataSize = 0; - var buffer = new typedarrayBuffer(bitBuffer.buffer); - - // Divide the buffer into the required number of blocks - for (var b = 0; b < ecTotalBlocks; b++) { - var dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2; - - // extract a block of data from buffer - dcData[b] = buffer.slice(offset, offset + dataSize); - - // Calculate EC codewords for this data block - ecData[b] = rs.encode(dcData[b]); - - offset += dataSize; - maxDataSize = Math.max(maxDataSize, dataSize); - } - - // Create final data - // Interleave the data and error correction codewords from each block - var data = new typedarrayBuffer(totalCodewords); - var index = 0; - var i, r; - - // Add data codewords - for (i = 0; i < maxDataSize; i++) { - for (r = 0; r < ecTotalBlocks; r++) { - if (i < dcData[r].length) { - data[index++] = dcData[r][i]; - } - } - } - - // Apped EC codewords - for (i = 0; i < ecCount; i++) { - for (r = 0; r < ecTotalBlocks; r++) { - data[index++] = ecData[r][i]; - } - } - - return data - } - - /** - * Build QR Code symbol - * - * @param {String} data Input string - * @param {Number} version QR Code version - * @param {ErrorCorretionLevel} errorCorrectionLevel Error level - * @return {Object} Object containing symbol data - */ - function createSymbol (data, version$1, errorCorrectionLevel) { - var segments$1; - - if (isarray(data)) { - segments$1 = segments.fromArray(data); - } else if (typeof data === 'string') { - var estimatedVersion = version$1; - - if (!estimatedVersion) { - var rawSegments = segments.rawSplit(data); - - // Estimate best version that can contain raw splitted segments - estimatedVersion = version.getBestVersionForData(rawSegments, - errorCorrectionLevel); - } - - // Build optimized segments - // If estimated version is undefined, try with the highest version - segments$1 = segments.fromString(data, estimatedVersion); - } else { - throw new Error('Invalid data') - } - - // Get the min version that can contain data - var bestVersion = version.getBestVersionForData(segments$1, - errorCorrectionLevel); - - // If no version is found, data cannot be stored - if (!bestVersion) { - throw new Error('The amount of data is too big to be stored in a QR Code') - } - - // If not specified, use min version as default - if (!version$1) { - version$1 = bestVersion; - - // Check if the specified version can contain the data - } else if (version$1 < bestVersion) { - throw new Error('\n' + - 'The chosen QR Code version cannot contain this amount of data.\n' + - 'Minimum version required to store current data is: ' + bestVersion + '.\n' - ) - } - - var dataBits = createData(version$1, errorCorrectionLevel, segments$1); - - // Allocate matrix buffer - var moduleCount = utils.getSymbolSize(version$1); - var modules = new bitMatrix(moduleCount); - - // Add function modules - setupFinderPattern(modules, version$1); - setupTimingPattern(modules); - setupAlignmentPattern(modules, version$1); - - // Add temporary dummy bits for format info just to set them as reserved. - // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask} - // since the masking operation must be performed only on the encoding region. - // These blocks will be replaced with correct values later in code. - setupFormatInfo(modules, errorCorrectionLevel, 0); - - if (version$1 >= 7) { - setupVersionInfo(modules, version$1); - } - - // Add data codewords - setupData(modules, dataBits); - - // Find best mask pattern - var maskPattern$1 = maskPattern.getBestMask(modules, - setupFormatInfo.bind(null, modules, errorCorrectionLevel)); - - // Apply mask pattern - maskPattern.applyMask(maskPattern$1, modules); - - // Replace format info bits with correct values - setupFormatInfo(modules, errorCorrectionLevel, maskPattern$1); - - return { - modules: modules, - version: version$1, - errorCorrectionLevel: errorCorrectionLevel, - maskPattern: maskPattern$1, - segments: segments$1 - } - } - - /** - * QR Code - * - * @param {String | Array} data Input data - * @param {Object} options Optional configurations - * @param {Number} options.version QR Code version - * @param {String} options.errorCorrectionLevel Error correction level - * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis - */ - var create = function create (data, options) { - if (typeof data === 'undefined' || data === '') { - throw new Error('No input text') - } - - var errorCorrectionLevel$1 = errorCorrectionLevel.M; - var version$1; - - if (typeof options !== 'undefined') { - // Use higher error correction level as default - errorCorrectionLevel$1 = errorCorrectionLevel.from(options.errorCorrectionLevel, errorCorrectionLevel.M); - version$1 = version.from(options.version); - - if (options.toSJISFunc) { - utils.setToSJISFunction(options.toSJISFunc); - } - } - - return createSymbol(data, version$1, errorCorrectionLevel$1) - }; - - var qrcode = { - create: create - }; - - function hex2rgba (hex) { - if (typeof hex !== 'string') { - throw new Error('Color should be defined as hex string') - } - - var hexCode = hex.slice().replace('#', '').split(''); - if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) { - throw new Error('Invalid hex color: ' + hex) - } - - // Convert from short to long form (fff -> ffffff) - if (hexCode.length === 3 || hexCode.length === 4) { - hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) { - return [c, c] - })); - } - - // Add default alpha value - if (hexCode.length === 6) hexCode.push('F', 'F'); - - var hexValue = parseInt(hexCode.join(''), 16); - - return { - r: (hexValue >> 24) & 255, - g: (hexValue >> 16) & 255, - b: (hexValue >> 8) & 255, - a: hexValue & 255 - } - } - - var getOptions = function getOptions (options) { - if (!options) options = {}; - if (!options.color) options.color = {}; - - var margin = typeof options.margin === 'undefined' || - options.margin === null || - options.margin < 0 ? 4 : options.margin; - - return { - scale: options.scale || 4, - margin: margin, - color: { - dark: hex2rgba(options.color.dark || '#000000ff'), - light: hex2rgba(options.color.light || '#ffffffff') - }, - type: options.type, - rendererOpts: options.rendererOpts || {} - } - }; - - var qrToImageData = function qrToImageData (imgData, qr, margin, scale, color) { - var size = qr.modules.size; - var data = qr.modules.data; - var scaledMargin = margin * scale; - var symbolSize = size * scale + scaledMargin * 2; - var palette = [color.light, color.dark]; - - for (var i = 0; i < symbolSize; i++) { - for (var j = 0; j < symbolSize; j++) { - var posDst = (i * symbolSize + j) * 4; - var pxColor = color.light; - - if (i >= scaledMargin && j >= scaledMargin && - i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) { - var iSrc = Math.floor((i - scaledMargin) / scale); - var jSrc = Math.floor((j - scaledMargin) / scale); - pxColor = palette[data[iSrc * size + jSrc]]; - } - - imgData[posDst++] = pxColor.r; - imgData[posDst++] = pxColor.g; - imgData[posDst++] = pxColor.b; - imgData[posDst] = pxColor.a; - } - } - }; - - var utils$1 = { - getOptions: getOptions, - qrToImageData: qrToImageData - }; - - var canvas = createCommonjsModule(function (module, exports) { - function clearCanvas (ctx, canvas, size) { - ctx.clearRect(0, 0, canvas.width, canvas.height); - - if (!canvas.style) canvas.style = {}; - canvas.height = size; - canvas.width = size; - canvas.style.height = size + 'px'; - canvas.style.width = size + 'px'; - } - - function getCanvasElement () { - try { - return document.createElement('canvas') - } catch (e) { - throw new Error('You need to specify a canvas element') - } - } - - exports.render = function render (qrData, canvas, options) { - var opts = options; - var canvasEl = canvas; - - if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { - opts = canvas; - canvas = undefined; - } - - if (!canvas) { - canvasEl = getCanvasElement(); - } - - opts = utils$1.getOptions(opts); - var size = (qrData.modules.size + opts.margin * 2) * opts.scale; - - var ctx = canvasEl.getContext('2d'); - var image = ctx.createImageData(size, size); - utils$1.qrToImageData(image.data, qrData, opts.margin, opts.scale, opts.color); - - clearCanvas(ctx, canvasEl, size); - ctx.putImageData(image, 0, 0); - - return canvasEl - }; - - exports.renderToDataURL = function renderToDataURL (qrData, canvas, options) { - var opts = options; - - if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { - opts = canvas; - canvas = undefined; - } - - if (!opts) opts = {}; - - var canvasEl = exports.render(qrData, canvas, opts); - - var type = opts.type || 'image/png'; - var rendererOpts = opts.rendererOpts || {}; - - return canvasEl.toDataURL(type, rendererOpts.quality) - }; - }); - var canvas_1 = canvas.render; - var canvas_2 = canvas.renderToDataURL; - - function getColorAttrib (color) { - return 'fill="rgb(' + [color.r, color.g, color.b].join(',') + ')" ' + - 'fill-opacity="' + (color.a / 255).toFixed(2) + '"' - } - - var render = function render (qrData, options) { - var opts = utils$1.getOptions(options); - var size = qrData.modules.size; - var data = qrData.modules.data; - var qrcodesize = (size + opts.margin * 2) * opts.scale; - - var xmlStr = '\n'; - xmlStr += '\n'; - - xmlStr += '\n'; - xmlStr += '\n'; - xmlStr += '\n'; - - for (var i = 0; i < size; i++) { - for (var j = 0; j < size; j++) { - if (!data[i * size + j]) continue - - var x = (opts.margin + j) * opts.scale; - var y = (opts.margin + i) * opts.scale; - xmlStr += '\n'; - } - } - - xmlStr += '\n'; - xmlStr += ''; - - return xmlStr - }; - - var svgRender = { - render: render - }; - - var browser = createCommonjsModule(function (module, exports) { - function renderCanvas (renderFunc, canvas, text, opts, cb) { - var argsNum = arguments.length - 1; - if (argsNum < 2) { - throw new Error('Too few arguments provided') - } - - if (argsNum === 2) { - cb = text; - text = canvas; - canvas = opts = undefined; - } else if (argsNum === 3) { - if (canvas.getContext && typeof cb === 'undefined') { - cb = opts; - opts = undefined; - } else { - cb = opts; - opts = text; - text = canvas; - canvas = undefined; - } - } - - if (typeof cb !== 'function') { - throw new Error('Callback required as last argument') - } - - try { - var data = qrcode.create(text, opts); - cb(null, renderFunc(data, canvas, opts)); - } catch (e) { - cb(e); - } - } - - exports.create = qrcode.create; - exports.toCanvas = renderCanvas.bind(null, canvas.render); - exports.toDataURL = renderCanvas.bind(null, canvas.renderToDataURL); - - // only svg for now. - exports.toString = renderCanvas.bind(null, function (data, _, opts) { - return svgRender.render(data, opts) - }); - - /** - * Legacy API - */ - exports.qrcodedraw = function () { - return { - draw: exports.toCanvas - } - }; - }); - var browser_1 = browser.create; - var browser_2 = browser.toCanvas; - var browser_3 = browser.toDataURL; - var browser_4 = browser.qrcodedraw; - - var isMobile = function isMobile() { - return navigator && ('userAgent' in navigator && navigator.userAgent.match(/iPhone|iPod|iPad|Android/i) || navigator.maxTouchPoints > 1 && navigator.platform === 'MacIntel'); - }; - - var removeLoader = function removeLoader(element) { - while (element.firstChild) { - element.removeChild(element.firstChild); - } - }; - - var haveStyleSheet = false; - - var setLoader = function setLoader(element, styles) { - var loaderClass = "".concat(styles.prefix || 'wwp_', "qrcode_loader"); - var loader = document.createElement('div'); - loader.className = loaderClass; - loader.innerHTML = "
\n
\n
\n
"); - - if (!haveStyleSheet) { - var style = document.createElement('style'); - style.innerHTML = "@keyframes ".concat(styles.prefix || 'wwp_', "pulse {\n 0% { opacity: 1; }\n 100% { opacity: 0; }\n }\n .").concat(loaderClass, " {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-around;\n align-items: center;\n width: 30%;\n height: 30%;\n margin-left: 35%;\n padding-top: 35%;\n }\n .").concat(loaderClass, "_blk {\n height: 35%;\n width: 35%;\n animation: ").concat(styles.prefix || 'wwp_', "pulse 0.75s ease-in infinite alternate;\n background-color: #cccccc;\n }\n .").concat(loaderClass, "_delay {\n animation-delay: 0.75s;\n }"); - document.getElementsByTagName('head')[0].appendChild(style); - haveStyleSheet = true; - } - - removeLoader(element); - element.appendChild(loader); - }; - - var setRefersh = function setRefersh(element, error) { - var httpsRequired = error instanceof WWPassError && error.code === WWPASS_STATUS.SSL_REQUIRED; - var offline = window.navigator.onLine !== undefined && !window.navigator.onLine; - var wrapper = document.createElement('div'); - wrapper.style.display = 'flex'; - wrapper.style.alignItems = 'center'; - wrapper.style.height = '100%'; - wrapper.style.width = '100%'; - var refreshNote = document.createElement('div'); - refreshNote.style.margin = '0 10%'; - refreshNote.style.width = '80%'; - refreshNote.style.textAlign = 'center'; - refreshNote.style.overflow = 'hidden'; - var text = 'Error occured'; - - if (httpsRequired) { - text = 'Please use HTTPS'; - } else if (offline) { - text = 'No internet connection'; - } - - refreshNote.innerHTML = "

".concat(text, "

"); - var refreshButton = null; - - if (!httpsRequired) { - refreshButton = document.createElement('a'); - refreshButton.textContent = 'Retry'; - refreshButton.style.fontWeight = '400'; - refreshButton.style.fontFamily = '"Arial", sans-serif'; - refreshButton.style.fontSize = '1.2em'; - refreshButton.style.lineHeight = '1.7em'; - refreshButton.style.cursor = 'pointer'; - refreshButton.href = '#'; - refreshNote.appendChild(refreshButton); - } - - wrapper.appendChild(refreshNote); // eslint-disable-next-line no-console - - console.error("Error in WWPass Library: ".concat(error)); - removeLoader(element); - element.appendChild(wrapper); - return httpsRequired ? Promise.reject(error.message) : new Promise(function (resolve) { - // Refresh after 1 minute or on click - setTimeout(function () { - resolve({ - refresh: true - }); - }, 60000); - refreshButton.addEventListener('click', function (event) { - resolve({ - refresh: true - }); - event.preventDefault(); - }); - - if (offline) { - window.addEventListener('online', function () { - return resolve({ - refresh: true - }); - }); - } - }); - }; - - var debouncePageVisibilityFactory = function debouncePageVisibilityFactory() { - var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'visible'; - var debounce = null; - return function (fn) { - debounce = fn; - - var onDebounce = function onDebounce() { - if (document.visibilityState === state) { - debounce(); - document.removeEventListener('visibilitychange', onDebounce); - } - }; - - if (document.visibilityState === state) { - debounce(); - } else { - document.addEventListener('visibilitychange', onDebounce); - } - }; - }; - - var debouncePageVisible = debouncePageVisibilityFactory(); - - var QRCodePromise = function QRCodePromise(parentElement, wwpassURLoptions, ttl, qrcodeStyle) { - return new Promise(function (resolve) { - var QRCodeElement = document.createElement('canvas'); - browser.toCanvas(QRCodeElement, getUniversalURL(wwpassURLoptions, false), qrcodeStyle || {}, function (error) { - if (error) { - throw error; - } - }); - - if (qrcodeStyle) { - QRCodeElement.className = "".concat(qrcodeStyle.prefix, "qrcode_canvas"); - QRCodeElement.style.max_width = "".concat(qrcodeStyle.width, "px"); - QRCodeElement.style.max_height = "".concat(qrcodeStyle.width, "px"); - } - - QRCodeElement.style.height = '100%'; - QRCodeElement.style.width = '100%'; - - if (isMobile()) { - // Wrapping QRCode canvas in - var universalLinkElement = document.createElement('a'); - universalLinkElement.href = getUniversalURL(wwpassURLoptions); - universalLinkElement.appendChild(QRCodeElement); - universalLinkElement.addEventListener('click', function () { - resolve({ - away: true - }); - }); - QRCodeElement = universalLinkElement; - } - - removeLoader(parentElement); - parentElement.appendChild(QRCodeElement); - setTimeout(function () { - debouncePageVisible(function () { - resolve({ - refresh: true - }); - }); - }, ttl * 900); - }); - }; - - var clearQRCode = function clearQRCode(parentElement, style) { - return setLoader(parentElement, style); - }; - - // const DEFAULT_WAIT_CLASS = 'focused'; - // style.transition = 'all .4s ease-out'; - // style.opacity = '.3'; - - var PROTOCOL_VERSION = 2; - var WAIT_ON_CLICK = 2000; - var WAIT_ON_ERROR = 500; - - function wait(ms) { - if (ms) return new Promise(function (r) { - return setTimeout(r, ms); - }); - return null; - } - - var tryQRCodeAuth = - /*#__PURE__*/ - function () { - var _ref = asyncToGenerator( - /*#__PURE__*/ - regenerator.mark(function _callee(options) { - var log, json, response, ticket, ttl, key, wwpassURLoptions, result; - return regenerator.wrap(function _callee$(_context) { - while (1) { - switch (_context.prev = _context.next) { - case 0: - log = options.log; - _context.prev = 1; - log(options); - clearQRCode(options.qrcode, options.qrcodeStyle); - _context.next = 6; - return getTicket(options.ticketURL); - - case 6: - json = _context.sent; - response = ticketAdapter(json); - ticket = response.ticket; - ttl = response.ttl; - _context.next = 12; - return getClientNonceWrapper(ticket, ttl); - - case 12: - key = _context.sent; - wwpassURLoptions = { - universal: options.universal, - ticket: ticket, - callbackURL: options.callbackURL, - ppx: options.ppx, - version: PROTOCOL_VERSION, - clientKey: key ? encodeClientKey(key) : undefined - }; - _context.next = 16; - return Promise.race([QRCodePromise(options.qrcode, wwpassURLoptions, ttl, options.qrcodeStyle), getWebSocketResult({ - callbackURL: options.callbackURL, - ticket: ticket, - log: log, - development: options.development, - version: options.version, - ppx: options.ppx, - spfewsAddress: options.spfewsAddress, - returnErrors: options.returnErrors - })]); - - case 16: - result = _context.sent; - clearQRCode(options.qrcode, options.qrcodeStyle); - - if (!result.refresh) { - _context.next = 20; - break; - } - - return _context.abrupt("return", { - status: WWPASS_STATUS.CONTINUE, - reason: 'Need to refresh QRCode' - }); - - case 20: - if (result.clientKey && options.catchClientKey) { - options.catchClientKey(result.clientKey); - } - - if (!result.away) { - _context.next = 24; - break; - } - - closeConnectionPool(); - return _context.abrupt("return", { - status: WWPASS_STATUS.OK, - reason: 'User clicked on QRCode' - }); - - case 24: - return _context.abrupt("return", result); - - case 27: - _context.prev = 27; - _context.t0 = _context["catch"](1); - - if (_context.t0.status) { - _context.next = 35; - break; - } - - log('QRCode auth error', _context.t0); - _context.next = 33; - return setRefersh(options.qrcode, _context.t0); - - case 33: - clearQRCode(options.qrcode, options.qrcodeStyle); - return _context.abrupt("return", { - status: WWPASS_STATUS.NETWORK_ERROR, - reason: _context.t0 - }); - - case 35: - clearQRCode(options.qrcode, options.qrcodeStyle); - - if (!(_context.t0.status === WWPASS_STATUS.INTERNAL_ERROR || options.returnErrors)) { - _context.next = 39; - break; - } - - navigateToCallback(_context.t0); - return _context.abrupt("return", _context.t0); - - case 39: - if (_context.t0.status === WWPASS_STATUS.TICKET_TIMEOUT) { - log('ticket timed out'); - } - - return _context.abrupt("return", _context.t0); - - case 41: - case "end": - return _context.stop(); - } - } - }, _callee, null, [[1, 27]]); - })); - - return function tryQRCodeAuth(_x) { - return _ref.apply(this, arguments); - }; - }(); - - var getDelay = function getDelay(status) { - switch (status) { - case WWPASS_STATUS.OK: - return WAIT_ON_CLICK; - - case WWPASS_STATUS.CONTINUE: - return 0; - - default: - return WAIT_ON_ERROR; - } - }; - /* - * WWPass QR code auth function - * - options = { - 'ticketURL': undefined, // string - 'callbackURL': undefined, // string - 'development': false, // work with dev server - 'log': function (message) || console.log, // another log handler - } - */ - - - var wwpassQRCodeAuth = - /*#__PURE__*/ - function () { - var _ref2 = asyncToGenerator( - /*#__PURE__*/ - regenerator.mark(function _callee2(initialOptions) { - var defaultOptions, options, result; - return regenerator.wrap(function _callee2$(_context2) { - while (1) { - switch (_context2.prev = _context2.next) { - case 0: - defaultOptions = { - universal: false, - ticketURL: undefined, - callbackURL: undefined, - development: false, - once: false, - // Repeat authentication while possible - version: 2, - ppx: 'wwp_', - spfewsAddress: 'wss://spfews.wwpass.com', - qrcodeStyle: { - width: 256, - prefix: 'wwp_' - }, - log: function log() {} - }; - options = objectSpread({}, defaultOptions, initialOptions); - options.qrcodeStyle = objectSpread({}, defaultOptions.qrcodeStyle, initialOptions.qrcodeStyle); - - if (options.ticketURL) { - _context2.next = 5; - break; - } - - throw Error('ticketURL not found'); - - case 5: - if (options.callbackURL) { - _context2.next = 7; - break; - } - - throw Error('callbackURL not found'); - - case 7: - if (options.qrcode) { - _context2.next = 9; - break; - } - - throw Error('Element not found'); - - case 9: - _context2.next = 11; - return tryQRCodeAuth(options); - - case 11: - result = _context2.sent; - - if (!(options.once && result.status !== WWPASS_STATUS.CONTINUE)) { - _context2.next = 14; - break; - } - - return _context2.abrupt("return", result); - - case 14: - _context2.next = 16; - return wait(getDelay(result.status)); - - case 16: - if (document.documentElement.contains(options.qrcode)) { - _context2.next = 9; - break; - } - - case 17: - return _context2.abrupt("return", { - status: WWPASS_STATUS.TERMINAL_ERROR, - reason: 'QRCode element is not in DOM' - }); - - case 18: - case "end": - return _context2.stop(); - } - } - }, _callee2); - })); - - return function wwpassQRCodeAuth(_x2) { - return _ref2.apply(this, arguments); - }; - }(); - - var openWithTicket = function openWithTicket(initialOptions) { - return new Promise(function (resolve) { - var defaultOptions = { - ticket: '', - ttl: 120, - callbackURL: '', - ppx: 'wwp_', - away: true - }; - - var options = objectSpread({}, defaultOptions, initialOptions); - - if (isClientKeyTicket(options.ticket)) { - generateClientNonce(options.ticket, options.ttl).then(function (key) { - options = objectSpread({}, options, { - clientKey: encodeClientKey(key) - }); - var url = getUniversalURL(options); - - if (options.away) { - window.location.href = url; - } else { - resolve(url); - } - }); - } else { - var url = getUniversalURL(options); - - if (options.away) { - window.location.href = url; - } else { - resolve(url); - } - } - }); - }; - - var prefix = window.location.protocol === 'https:' ? 'https:' : 'http:'; - var CSS = "".concat(prefix, "//cdn.wwpass.com/packages/wwpass.js/2.4/wwpass.js.css"); - - var isNativeMessaging = function isNativeMessaging() { - var _navigator = navigator, - userAgent = _navigator.userAgent; - var re = /Firefox\/([0-9]+)\./; - var match = userAgent.match(re); - - if (match && match.length > 1) { - var version = match[1]; - - if (Number(version) >= 51) { - return 'Firefox'; - } - } - - re = /Chrome\/([0-9]+)\./; - match = userAgent.match(re); - - if (match && match.length > 1) { - var _version = match[1]; - - if (Number(_version) >= 45) { - return 'Chrome'; - } - } - - return false; - }; - - var wwpassPlatformName = function wwpassPlatformName() { - var _navigator2 = navigator, - userAgent = _navigator2.userAgent; - var knownPlatforms = ['Android', 'iPhone', 'iPad']; - - for (var i = 0; i < knownPlatforms.length; i += 1) { - if (userAgent.search(new RegExp(knownPlatforms[i], 'i')) !== -1) { - return knownPlatforms[i]; - } - } - - return null; - }; - - var wwpassMessageForPlatform = function wwpassMessageForPlatform(platformName) { - return "".concat(WWPASS_UNSUPPORTED_PLATFORM_MSG_TMPL, " ").concat(platformName); - }; - - var wwpassShowError = function wwpassShowError(message, title, onCloseCallback) { - if (!document.getElementById('_wwpass_css')) { - var l = document.createElement('link'); - l.id = '_wwpass_css'; - l.rel = 'stylesheet'; - l.href = CSS; - document.head.appendChild(l); - } - - var dlg = document.createElement('div'); - dlg.id = '_wwpass_err_dlg'; - var dlgClose = document.createElement('span'); - dlgClose.innerHTML = 'Close'; - dlgClose.id = '_wwpass_err_close'; - var header = document.createElement('h1'); - header.innerHTML = title; - var text = document.createElement('div'); - text.innerHTML = message; - dlg.appendChild(header); - dlg.appendChild(text); - dlg.appendChild(dlgClose); - document.body.appendChild(dlg); - document.getElementById('_wwpass_err_close').addEventListener('click', function () { - var elem = document.getElementById('_wwpass_err_dlg'); - elem.parentNode.removeChild(elem); - onCloseCallback(); - return false; - }); - return true; - }; - - var wwpassNoSoftware = function wwpassNoSoftware(code, onclose) { - if (code === WWPASS_STATUS.NO_AUTH_INTERFACES_FOUND) { - var client = isNativeMessaging(); - var message = ''; - - if (client) { - if (client === 'Chrome') { - var returnURL = encodeURIComponent(window.location.href); - message = '

The WWPass Authentication extension for Chrome is not installed or is disabled in browser settings.'; - message += '

Click the link below to install and enable the WWPass Authentication extension.'; - message += "

Install WWPass Authentication Extension"); - } else if (client === 'Firefox') { - // Firefox - var _returnURL = encodeURIComponent(window.location.href); - - message = '

The WWPass Authentication extension for Firefox is not installed or is disabled in browser settings.'; - message += '

Click the link below to install and enable the WWPass Authentication extension.'; - message += "

Install WWPass Authentication Extension"); - } - } else { - message = '

No Security Pack is found on your computer or WWPass Browser Plugin is disabled.

To install Security Pack visit Key Services or check plugin settings of your browser to activate WWPass Browser Plugin.

Learn more...

'; - } - - wwpassShowError(message, 'WWPass — No Software Found', onclose); - } else if (code === WWPASS_STATUS.UNSUPPORTED_PLATFORM) { - wwpassShowError(wwpassMessageForPlatform(wwpassPlatformName()), 'WWPass — Unsupported Platform', onclose); - } - }; - - var renderPassKeyButton = function renderPassKeyButton() { - var button = document.createElement('button'); - button.innerHTML = ' Log in with PassKey'; - button.setAttribute('style', 'color: white; background-color: #2277E6; font-weight: 400; font-size: 18px; line-height: 36px; font-family: "Arial", sans-serif; padding-right: 15px; cursor: pointer; height: 40px; width: 255px; border-radius: 3px; border: 1px solid #2277E6; padding-left: 60px; text-decoration: none; position: relative;'); - return button; - }; - - var PLUGIN_OBJECT_ID = '_wwpass_plugin'; - var PLUGIN_MIME_TYPE = 'application/x-wwauth'; - var PLUGIN_TIMEOUT = 10000; - var REDUCED_PLUGIN_TIMEOUT = 1000; - var PLUGIN_AUTH_KEYTYPE_REVISION = 9701; - var PluginInfo = {}; - var savedPluginInstance; - var pendingReqests = []; - - var havePlugin = function havePlugin() { - return navigator.mimeTypes[PLUGIN_MIME_TYPE] !== undefined; - }; - - var wwpassPluginShowsErrors = function wwpassPluginShowsErrors(pluginVersionString) { - if (typeof pluginVersionString === 'string') { - var pluginVersion = pluginVersionString.split('.'); - - for (var i = 0; i < pluginVersion.length; i += 1) { - pluginVersion[i] = parseInt(pluginVersion[i], 10); - } - - if (pluginVersion.length === 3) { - if (pluginVersion[0] > 2 || pluginVersion[0] === 2 && pluginVersion[1] > 4 || pluginVersion[0] === 2 && pluginVersion[1] === 4 && pluginVersion[2] >= 1305) { - return true; - } - } - } - - return false; - }; - - var getPluginInstance = function getPluginInstance(log) { - return new Promise(function (resolve, reject) { - if (savedPluginInstance) { - if (window._wwpass_plugin_loaded !== undefined) { - // eslint-disable-line no-underscore-dangle - pendingReqests.push([resolve, reject]); - } else { - log('%s: plugin is already initialized', 'getPluginInstance'); - resolve(savedPluginInstance); - } - } else { - var junkBrowser = navigator.mimeTypes.length === 0; - var pluginInstalled = havePlugin(); - var timeout = junkBrowser ? REDUCED_PLUGIN_TIMEOUT : PLUGIN_TIMEOUT; - - if (pluginInstalled || junkBrowser) { - log('%s: trying to create plugin instance(junkBrowser=%s, timeout=%d)', 'getPluginInstance', junkBrowser, timeout); - var pluginHtml = ""); - var pluginDiv = document.createElement('div'); - pluginDiv.setAttribute('style', 'position: fixed; left: 0; top:0; width: 1px; height: 1px; z-index: -1; opacity: 0.01'); - document.body.appendChild(pluginDiv); - pluginDiv.innerHTML += pluginHtml; - savedPluginInstance = document.getElementById(PLUGIN_OBJECT_ID); - var timer = setTimeout(function () { - delete window._wwpass_plugin_loaded; // eslint-disable-line no-underscore-dangle - - savedPluginInstance = null; - log('%s: WWPass plugin loading timeout', 'getPluginInstance'); - reject({ - code: WWPASS_STATUS.NO_AUTH_INTERFACES_FOUND, - message: WWPASS_NO_AUTH_INTERFACES_FOUND_MSG - }); - - for (var i = 0; i < pendingReqests.length; i += 1) { - var pendingReject = pendingReqests[i][1]; - pendingReject({ - code: WWPASS_STATUS.NO_AUTH_INTERFACES_FOUND, - message: WWPASS_NO_AUTH_INTERFACES_FOUND_MSG - }); - } - }, PLUGIN_TIMEOUT); - - window._wwpass_plugin_loaded = function () { - // eslint-disable-line no-underscore-dangle - log('%s: plugin loaded', 'getPluginInstance'); - delete window._wwpass_plugin_loaded; // eslint-disable-line no-underscore-dangle - - clearTimeout(timer); - - try { - PluginInfo.versionString = savedPluginInstance.version; - PluginInfo.revision = parseInt(savedPluginInstance.version.split('.')[2], 10); - PluginInfo.showsErrors = wwpassPluginShowsErrors(PluginInfo.versionString); - } catch (err) { - log('%s: error parsing plugin version: %s', 'getPluginInstance', err); - } - - resolve(savedPluginInstance); - - for (var i = 0; i < pendingReqests.length; i += 1) { - var pendingResolve = pendingReqests[i][0]; - pendingResolve(savedPluginInstance); - } - }; - } else { - log('%s: no suitable plugins installed', 'getPluginInstance'); - reject({ - code: WWPASS_STATUS.NO_AUTH_INTERFACES_FOUND, - message: WWPASS_NO_AUTH_INTERFACES_FOUND_MSG - }); - } - } - }); - }; - - var wrapCallback = function wrapCallback(callback) { - if (!PluginInfo.showsErrors) { - return function (code, ticketOrMessage) { - if (code !== WWPASS_STATUS.OK && code !== WWPASS_STATUS.USER_REJECT) { - var message = "

A error has occured: ".concat(ticketOrMessage, "

") + "

Learn more

"); - wwpassShowError(message, 'WWPass Error', function () { - callback(code, ticketOrMessage); - }); - } else { - callback(code, ticketOrMessage); - } - }; - } - - return callback; - }; - - var wwpassPluginExecute = function wwpassPluginExecute(inputRequest) { - return new Promise(function (resolve, reject) { - var defaultOptions = { - log: function log() {} - }; - - var request = objectSpread({}, defaultOptions, inputRequest); - - request.log('%s: called, operation name is "%s"', 'wwpassPluginExecute', request.operation || null); - getPluginInstance(request.log).then(function (plugin) { - var wrappedCallback = wrapCallback(function (code, ticketOrMessage) { - if (code === WWPASS_STATUS.OK) { - resolve(ticketOrMessage); - } else { - reject({ - code: code, - message: ticketOrMessage - }); - } - }); - - if (plugin.execute !== undefined) { - request.callback = wrappedCallback; - plugin.execute(request); - } else if (request.operation === 'auth') { - if (PluginInfo.revision < PLUGIN_AUTH_KEYTYPE_REVISION) { - plugin.authenticate(request.ticket, wrappedCallback); - } else { - plugin.authenticate(request.ticket, wrappedCallback, request.firstKeyType || WWPASS_KEY_TYPE_DEFAULT); - } - } else { - plugin.do_operation(request.operation, wrappedCallback); - } - }).catch(reject); - }); - }; - - var pluginWaitForRemoval = function pluginWaitForRemoval() { - var log = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; - return new Promise(function (resolve, reject) { - getPluginInstance(log).then(function (plugin) { - plugin.on_key_removed(resolve); - }).catch(reject); - }); - }; - - var EXTENSION_POLL_TIMEOUT = 200; - var EXTENSION_POLL_ATTEMPTS = 15; - var extensionNotInstalled = false; - - var timedPoll = function timedPoll(args) { - var condition = args.condition; - - if (typeof condition === 'function') { - condition = condition(); - } - - if (condition) { - args.onCondition(); - } else { - var attempts = args.attempts || 0; - - if (attempts--) { - // eslint-disable-line no-plusplus - var timeout = args.timeout || 100; - setTimeout(function (p) { - return function () { - timedPoll(p); - }; - }({ - timeout: timeout, - attempts: attempts, - condition: args.condition, - onCondition: args.onCondition, - onTimeout: args.onTimeout - }), timeout); - } else { - args.onTimeout(); - } - } - }; - - var isNativeMessagingExtensionReady = function isNativeMessagingExtensionReady() { - return (document.querySelector('meta[property="wwpass:extension:version"]') || document.getElementById('_WWAuth_Chrome_Installed_')) !== null; - }; - - var randomID = function randomID() { - return ((1 + Math.random()) * 0x100000000 | 0).toString(16).substring(1); - }; // eslint-disable-line no-bitwise,max-len - - - var wwpassNMCall = function wwpassNMCall(func, args) { - var log = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; - return new Promise(function (resolve, reject) { - if (extensionNotInstalled) { - log('%s: chrome native messaging extension is not installed', 'wwpassNMExecute'); - reject({ - code: WWPASS_STATUS.NO_AUTH_INTERFACES_FOUND, - message: WWPASS_NO_AUTH_INTERFACES_FOUND_MSG - }); - return; - } - - timedPoll({ - timeout: EXTENSION_POLL_TIMEOUT, - attempts: EXTENSION_POLL_ATTEMPTS, - condition: isNativeMessagingExtensionReady, - onCondition: function onCondition() { - var id = randomID(); - window.postMessage({ - type: '_WWAuth_Message', - src: 'client', - id: id, - func: func, - args: args ? JSON.parse(JSON.stringify(args)) : args - }, '*'); - window.addEventListener('message', function onMessageCallee(event) { - if (event.data.type === '_WWAuth_Message' && event.data.src === 'plugin' && event.data.id === id) { - window.removeEventListener('message', onMessageCallee, false); - - if (event.data.code === WWPASS_STATUS.NO_AUTH_INTERFACES_FOUND) { - var message = '

No Security Pack is found on your computer or WWPass native host is not responding.

To install Security Pack visit Key Services

Learn more...

'; - wwpassShowError(message, 'WWPass Error', function () { - reject({ - code: event.data.code, - message: event.data.ticketOrMessage - }); - }); - } else if (event.data.code === WWPASS_STATUS.OK) { - resolve(event.data.ticketOrMessage); - } else { - reject({ - code: event.data.code, - message: event.data.ticketOrMessage - }); - } - } - }, false); - }, - onTimeout: function onTimeout() { - extensionNotInstalled = true; - log('%s: chrome native messaging extension is not installed', 'wwpassNMExecute'); - reject({ - code: WWPASS_STATUS.NO_AUTH_INTERFACES_FOUND, - message: WWPASS_NO_AUTH_INTERFACES_FOUND_MSG - }); - } - }); - }); - }; - - var wwpassNMExecute = function wwpassNMExecute(inputRequest) { - var defaultOptions = { - log: function log() {} - }; - - var request = objectSpread({}, defaultOptions, inputRequest); - - var log = request.log; - delete request.log; - log('%s: called', 'wwpassNMExecute'); - request.uri = { - domain: window.location.hostname, - protocol: window.location.protocol - }; - return wwpassNMCall('exec', [request], log); - }; - - var nmWaitForRemoval = function nmWaitForRemoval() { - var log = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {}; - return wwpassNMCall('on_key_rm', undefined, log); - }; - - var pluginPresent = function pluginPresent() { - return havePlugin() || isNativeMessagingExtensionReady(); - }; - - var wwpassPlatformName$1 = function wwpassPlatformName() { - var _navigator = navigator, - userAgent = _navigator.userAgent; - var knownPlatforms = ['Android', 'iPhone', 'iPad']; - - for (var i = 0; i < knownPlatforms.length; i += 1) { - if (userAgent.search(new RegExp(knownPlatforms[i], 'i')) !== -1) { - return knownPlatforms[i]; - } - } - - return null; - }; // N.B. it call functions in REVERSE order - - - var chainedCall = function chainedCall(functions, request, resolve, reject) { - functions.pop()(request).then(resolve, function (e) { - if (e.code === WWPASS_STATUS.NO_AUTH_INTERFACES_FOUND) { - if (functions.length > 0) { - chainedCall(functions, request, resolve, reject); - } else { - wwpassNoSoftware(e.code, function () {}); - reject(e); - } - } else { - reject(e); - } - }); - }; - - var wwpassCall = function wwpassCall(nmFunc, pluginFunc, request) { - return new Promise(function (resolve, reject) { - var platformName = wwpassPlatformName$1(); - - if (platformName !== null) { - wwpassNoSoftware(WWPASS_STATUS.UNSUPPORTED_PLATFORM, function () { - reject({ - code: WWPASS_STATUS.UNSUPPORTED_PLATFORM, - message: wwpassMessageForPlatform(platformName) - }); - }); - return; - } - - if (havePlugin()) { - chainedCall([nmFunc, pluginFunc], request, resolve, reject); - } else { - chainedCall([pluginFunc, nmFunc], request, resolve, reject); - } - }); - }; - - var wwpassAuth = function wwpassAuth(request) { - return wwpassCall(wwpassNMExecute, wwpassPluginExecute, objectSpread({}, request, { - operation: 'auth' - })); - }; - - var waitForRemoval = function waitForRemoval() { - return wwpassCall(nmWaitForRemoval, pluginWaitForRemoval); - }; - - var doWWPassPasskeyAuth = function doWWPassPasskeyAuth(options) { - return getTicket(options.ticketURL).then(function (json) { - var response = ticketAdapter(json); - var ticket = response.ticket; - return getClientNonceWrapper(ticket, response.ttl).then(function (key) { - return wwpassAuth({ - ticket: ticket, - clientKeyNonce: key !== undefined ? abToB64(key) : undefined, - log: options.log - }); - }).then(function () { - return ticket; - }); - /* We may receive new ticket here but we need - * to keep the original one to find nonce */ - }); - }; - - var initPasskeyButton = function initPasskeyButton(options, resolve, reject) { - if (options.passkeyButton.innerHTML.length === 0) { - options.passkeyButton.appendChild(renderPassKeyButton()); - } - - var authUnderway = false; - options.passkeyButton.addEventListener('click', function (e) { - if (!authUnderway) { - authUnderway = true; - doWWPassPasskeyAuth(options).then(function (newTicket) { - authUnderway = false; - resolve({ - ppx: options.ppx, - version: options.version, - code: WWPASS_STATUS.OK, - message: WWPASS_OK_MSG, - ticket: newTicket, - callbackURL: options.callbackURL, - hw: true - }); - }, function (err) { - authUnderway = false; - - if (!err.code) { - options.log('passKey error', err); - } else if (err.code === WWPASS_STATUS.INTERNAL_ERROR || options.returnErrors) { - reject({ - ppx: options.ppx, - version: options.version, - code: err.code, - message: err.message, - callbackURL: options.callbackURL - }); - } - }); - } - - e.preventDefault(); - }, false); - }; - - var wwpassPasskeyAuth = function wwpassPasskeyAuth(initialOptions) { - return new Promise(function (resolve, reject) { - var defaultOptions = { - ticketURL: '', - callbackURL: '', - ppx: 'wwp_', - forcePasskeyButton: true, - log: function log() {} - }; - - var options = objectSpread({}, defaultOptions, initialOptions); - - if (!options.passkeyButton) { - reject({ - ppx: options.ppx, - version: options.version, - code: WWPASS_STATUS.INTERNAL_ERROR, - message: 'Cannot find passkey element', - callbackURL: options.callbackURL - }); - } - - if (options.forcePasskeyButton || pluginPresent()) { - if (options.passkeyButton.style.display === 'none') { - options.passkeyButton.style.display = null; - } - - initPasskeyButton(options, resolve, reject); - } else { - var displayBackup = options.passkeyButton.style.display; - options.passkeyButton.style.display = 'none'; - var observer = new MutationObserver(function (_mutationsList, _observer) { - if (pluginPresent()) { - _observer.disconnect(); - - options.passkeyButton.style.display = displayBackup === 'none' ? null : displayBackup; - initPasskeyButton(options, resolve, reject); - } - }); - observer.observe(document.head, { - childList: true - }); - } - }).then(navigateToCallback, navigateToCallback); - }; - - var absolutePath = function absolutePath(href) { - var link = document.createElement('a'); - link.href = href; - return link.href; - }; - - var authInit = function authInit(initialOptions) { - var defaultOptions = { - ticketURL: '', - callbackURL: '', - hw: false, - ppx: 'wwp_', - version: 2, - log: function log() {} - }; - - var options = objectSpread({}, defaultOptions, initialOptions); - - if (typeof options.callbackURL === 'string') { - options.callbackURL = absolutePath(options.callbackURL); - } - - options.passkeyButton = typeof options.passkey === 'string' ? document.querySelector(options.passkey) : options.passkey; - options.qrcode = typeof options.qrcode === 'string' ? document.querySelector(options.qrcode) : options.qrcode; - var promises = []; - - if (options.passkeyButton) { - promises.push(wwpassPasskeyAuth(options)); - } - - promises.push(wwpassQRCodeAuth(options)); - return Promise.race(promises); - }; - - var version$1 = "2.1.6"; - - if ('console' in window && window.console.log) { - window.console.log("WWPass frontend library version ".concat(version$1)); - } - - window.WWPass = { - authInit: authInit, - openWithTicket: openWithTicket, - isClientKeyTicket: isClientKeyTicket, - cryptoPromise: WWPassCryptoPromise, - copyClientNonce: copyClientNonce, - updateTicket: updateTicket, - pluginPresent: pluginPresent, - waitForRemoval: waitForRemoval, - STATUS: WWPASS_STATUS - }; - -}()); -//# sourceMappingURL=wwpass-frontend.js.map diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/ticket.json b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/ticket.json deleted file mode 100755 index bdff117ebee..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/ticket.json +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -if [[ "$QUERY_STRING" =~ ^p=.* ]] -then - auth_type="p" -fi - -echo "Content-type: application/json" -echo "" -curl "https://spfe.wwpass.com/get.json?auth_type=$auth_type" --cert /opt/wwpass_gluu/gluu_client.crt --key /opt/wwpass_gluu/gluu_client.key --cacert /opt/wwpass_gluu/wwpass.ca.crt -s diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpass.ca.crt b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpass.ca.crt deleted file mode 100644 index 19c91f55687..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpass.ca.crt +++ /dev/null @@ -1,35 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGATCCA+mgAwIBAgIJAN7JZUlglGn4MA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNV -BAYTAlVTMRswGQYDVQQKExJXV1Bhc3MgQ29ycG9yYXRpb24xKzApBgNVBAMTIldX -UGFzcyBDb3Jwb3JhdGlvbiBQcmltYXJ5IFJvb3QgQ0EwIhgPMjAxMjExMjgwOTAw -MDBaGA8yMDUyMTEyODA4NTk1OVowVzELMAkGA1UEBhMCVVMxGzAZBgNVBAoTEldX -UGFzcyBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiV1dQYXNzIENvcnBvcmF0aW9uIFBy -aW1hcnkgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMmF -pl1WX80osygWx4ZX8xGyYfHx8cpz29l5s/7mgQIYCrmUSLK9KtSryA0pmzrOFkyN -BuT0OU5ucCuv2WNgUriJZ78b8sekW1oXy2QXndZSs+CA+UoHFw0YqTEDO659/Tjk -NqlE5HMXdYvIb7jhcOAxC8gwAJFgAkQboaMIkuWsAnpOtKzrnkWHGz45qoyICjqz -feDcN0dh3ITMHXrYiwkVq5fGXHPbuJPbuBN+unnakbL3Ogk3yPnEcm6YV+HrxQ7S -Ky83q60Abdy8ft0RpSJeUkBjJVwiHu4y4j5iKC1tNgtV8qE9Zf2g5vAHzL3obqnu -IMr8JpmWp0MrrUa9jYOtKXk2LnZnfxurJ74NVk2RmuN5I/H0a/tUrHWtCE5pcVNk -b3vmoqeFsbTs2KDCMq/gzUhHU31l4Zrlz+9DfBUxlb5fNYB5lF4FnR+5/hKgo75+ -OaNjiSfp9gTH6YfFCpS0OlHmKhsRJlR2aIKpTUEG9hjSg3Oh7XlpJHhWolQQ2BeL -++3UOyRMTDSTZ1bGa92oz5nS+UUsE5noUZSjLM+KbaJjZGCxzO9y2wiFBbRSbhL2 -zXpUD2dMB1G30jZwytjn15VAMEOYizBoHEp2Nf9PNhsDGa32AcpJ2a0n89pbSOlu -yr/vEzYjJ2DZ/TWQQb7upi0G2kRX17UIZ5ZfhjmBAgMBAAGjgcswgcgwHQYDVR0O -BBYEFGu/H4b/gn8RzL7XKHBT6K4BQcl7MIGIBgNVHSMEgYAwfoAUa78fhv+CfxHM -vtcocFPorgFByXuhW6RZMFcxCzAJBgNVBAYTAlVTMRswGQYDVQQKExJXV1Bhc3Mg -Q29ycG9yYXRpb24xKzApBgNVBAMTIldXUGFzcyBDb3Jwb3JhdGlvbiBQcmltYXJ5 -IFJvb3QgQ0GCCQDeyWVJYJRp+DAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB -BjANBgkqhkiG9w0BAQsFAAOCAgEAE46CMikI7378mkC3qZyKcVxkNfLRe3eD4h04 -OO27rmfZj/cMrDDCt0Bn2t9LBUGBdXfZEn13gqn598F6lmLoObtN4QYqlyXrFcPz -FiwQarba+xq8togxjMkZ2y70MlV3/PbkKkwv4bBjOcLZQ1DsYehPdsr57C6Id4Ee -kEQs/aMtKcMzZaSipkTuXFxfxW4uBifkH++tUASD44OD2r7m1UlSQ5viiv3l0qvA -B89dPifVnIeAvPcd7+GY2RXTZCw36ZipnFiOWT9TkyTDpB/wjWQNFrgmmQvxQLeW -BWIUSaXJwlVzMztdtThnt/bNZNGPMRfaZ76OljYB9BKC7WUmss2f8toHiys+ERHz -0xfCTVhowlz8XtwWfb3A17jzJBm+KAlQsHPgeBEqtocxvBJcqhOiKDOpsKHHz+ng -exIO3elr1TCVutPTE+UczYTBRsL+jIdoIxm6aA9rrN3qDVwMnuHThSrsiwyqOXCz -zjCaCf4l5+KG5VNiYPytiGicv8PCBjwFkzIr+LRSyUiYzAZuiyRchpdT+yRAfL7q -qHBuIHYhG3E47a3GguwUwUGcXR+NjrSmteHRDONOUYUCH41hw6240Mo1lL4F+rpr -LEBB84k3+v+AtbXePEwvp+o1nu/+1sRkhqlNFHN67vakqC4xTxiuPxu6Pb/uDeNI -ip0+E9I= ------END CERTIFICATE----- diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpass.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpass.py deleted file mode 100644 index f31a20315ee..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpass.py +++ /dev/null @@ -1,248 +0,0 @@ -# -*- coding: utf-8 -*- -__author__="Rostislav Kondratenko " -__date__ ="$27.11.2014 18:05:15$" - -# Copyright 2009-2019 WWPASS Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pickle -from threading import Lock -import ssl -try: - # python3 - from urllib.request import urlopen - from urllib.parse import urlencode - from urllib.error import URLError -except ImportError: - # python2 - from urllib2 import urlopen, URLError - from urllib import urlencode - -DEFAULT_CADATA = u'''-----BEGIN CERTIFICATE----- -MIIGATCCA+mgAwIBAgIJAN7JZUlglGn4MA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNV -BAYTAlVTMRswGQYDVQQKExJXV1Bhc3MgQ29ycG9yYXRpb24xKzApBgNVBAMTIldX -UGFzcyBDb3Jwb3JhdGlvbiBQcmltYXJ5IFJvb3QgQ0EwIhgPMjAxMjExMjgwOTAw -MDBaGA8yMDUyMTEyODA4NTk1OVowVzELMAkGA1UEBhMCVVMxGzAZBgNVBAoTEldX -UGFzcyBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiV1dQYXNzIENvcnBvcmF0aW9uIFBy -aW1hcnkgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMmF -pl1WX80osygWx4ZX8xGyYfHx8cpz29l5s/7mgQIYCrmUSLK9KtSryA0pmzrOFkyN -BuT0OU5ucCuv2WNgUriJZ78b8sekW1oXy2QXndZSs+CA+UoHFw0YqTEDO659/Tjk -NqlE5HMXdYvIb7jhcOAxC8gwAJFgAkQboaMIkuWsAnpOtKzrnkWHGz45qoyICjqz -feDcN0dh3ITMHXrYiwkVq5fGXHPbuJPbuBN+unnakbL3Ogk3yPnEcm6YV+HrxQ7S -Ky83q60Abdy8ft0RpSJeUkBjJVwiHu4y4j5iKC1tNgtV8qE9Zf2g5vAHzL3obqnu -IMr8JpmWp0MrrUa9jYOtKXk2LnZnfxurJ74NVk2RmuN5I/H0a/tUrHWtCE5pcVNk -b3vmoqeFsbTs2KDCMq/gzUhHU31l4Zrlz+9DfBUxlb5fNYB5lF4FnR+5/hKgo75+ -OaNjiSfp9gTH6YfFCpS0OlHmKhsRJlR2aIKpTUEG9hjSg3Oh7XlpJHhWolQQ2BeL -++3UOyRMTDSTZ1bGa92oz5nS+UUsE5noUZSjLM+KbaJjZGCxzO9y2wiFBbRSbhL2 -zXpUD2dMB1G30jZwytjn15VAMEOYizBoHEp2Nf9PNhsDGa32AcpJ2a0n89pbSOlu -yr/vEzYjJ2DZ/TWQQb7upi0G2kRX17UIZ5ZfhjmBAgMBAAGjgcswgcgwHQYDVR0O -BBYEFGu/H4b/gn8RzL7XKHBT6K4BQcl7MIGIBgNVHSMEgYAwfoAUa78fhv+CfxHM -vtcocFPorgFByXuhW6RZMFcxCzAJBgNVBAYTAlVTMRswGQYDVQQKExJXV1Bhc3Mg -Q29ycG9yYXRpb24xKzApBgNVBAMTIldXUGFzcyBDb3Jwb3JhdGlvbiBQcmltYXJ5 -IFJvb3QgQ0GCCQDeyWVJYJRp+DAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB -BjANBgkqhkiG9w0BAQsFAAOCAgEAE46CMikI7378mkC3qZyKcVxkNfLRe3eD4h04 -OO27rmfZj/cMrDDCt0Bn2t9LBUGBdXfZEn13gqn598F6lmLoObtN4QYqlyXrFcPz -FiwQarba+xq8togxjMkZ2y70MlV3/PbkKkwv4bBjOcLZQ1DsYehPdsr57C6Id4Ee -kEQs/aMtKcMzZaSipkTuXFxfxW4uBifkH++tUASD44OD2r7m1UlSQ5viiv3l0qvA -B89dPifVnIeAvPcd7+GY2RXTZCw36ZipnFiOWT9TkyTDpB/wjWQNFrgmmQvxQLeW -BWIUSaXJwlVzMztdtThnt/bNZNGPMRfaZ76OljYB9BKC7WUmss2f8toHiys+ERHz -0xfCTVhowlz8XtwWfb3A17jzJBm+KAlQsHPgeBEqtocxvBJcqhOiKDOpsKHHz+ng -exIO3elr1TCVutPTE+UczYTBRsL+jIdoIxm6aA9rrN3qDVwMnuHThSrsiwyqOXCz -zjCaCf4l5+KG5VNiYPytiGicv8PCBjwFkzIr+LRSyUiYzAZuiyRchpdT+yRAfL7q -qHBuIHYhG3E47a3GguwUwUGcXR+NjrSmteHRDONOUYUCH41hw6240Mo1lL4F+rpr -LEBB84k3+v+AtbXePEwvp+o1nu/+1sRkhqlNFHN67vakqC4xTxiuPxu6Pb/uDeNI -ip0+E9I= ------END CERTIFICATE----- ''' - -PIN = 'p' -SESSION_KEY = 's' -CLIENT_KEY = 'c' - -class WWPassException(IOError): - pass - -class WWPassConnection(object): - - def __init__(self, key_file, cert_file, timeout=10, spfe_addr='https://spfe.wwpass.com', cafile=None): - """Construct class. - - Args: - key_file (str): ??? - cert_file (str): ?? - timeout (int): ?? - spfe_addr (str): ?? - cafile (str): ?? - """ - - self.context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLSv1) - self.context.load_cert_chain(certfile=cert_file, keyfile=key_file) - if cafile is None: - self.context.load_verify_locations(cadata=DEFAULT_CADATA) - else: - self.context.load_verify_locations(cafile=cafile) - self.spfe_addr = 'https://%s' % spfe_addr if spfe_addr.find('://') == -1 else spfe_addr - self.timeout = timeout - - def makeRequest(self, method, command, attempts=3,**paramsDict): - params = {k:v.encode('UTF-8') if hasattr(v,"encode") else v for k, v in paramsDict.items() if v is not None} - try: - if method == 'GET': - res = urlopen(self.spfe_addr +'/'+command+'?'+urlencode(params), context=self.context, timeout=self.timeout) - else: - res = urlopen(self.spfe_addr +'/'+command, data=urlencode(params).encode('UTF-8'), context=self.context, timeout=self.timeout) - res = pickle.loads(res.read()) - if not res['result']: - if 'code'in res: - raise WWPassException('SPFE returned error: %s: %s' %(res['code'], res['data'])) - raise WWPassException('SPFE returned error: %s' % res['data']) - return res - except URLError: - if attempts>0: - attempts -= 1 - else: - raise - return self.makeRequest(method, command, attempts,**params) - - @classmethod - def makeAuthTypeString(cls, auth_types): - valid_auth_types = (PIN, SESSION_KEY, CLIENT_KEY) - return ''.join(x for x in auth_types if x in valid_auth_types) - - def getName(self): - ticket = self.getTicket(ttl=0)['ticket'] - pos = ticket.find(':') - if pos == -1: - raise WWPassException('Cannot extract service provider name from ticket.') - return ticket[:pos] - - def getTicket(self, ttl=None, auth_types=()): - result = self.makeRequest('GET','get', ttl=ttl or None, auth_type=self.makeAuthTypeString(auth_types) or None) - return {'ticket' : result['data'], 'ttl' : result['ttl']} - - def getPUID(self, ticket, auth_types=(), finalize=None): - result = self.makeRequest('GET','puid', ticket=ticket, auth_type=self.makeAuthTypeString(auth_types) or None, finalize=finalize) - return {'puid' : result['data']} - - def putTicket(self, ticket, ttl=None, auth_types=(), finalize=None): - result = self.makeRequest('GET','put', ticket=ticket, ttl=ttl or None, auth_type=self.makeAuthTypeString(auth_types) or None, finalize=finalize) - return {'ticket' : result['data'], 'ttl' : result['ttl']} - - def readData(self, ticket, container=b'', finalize=None): - result = self.makeRequest('GET','read', ticket=ticket, container=container or None, finalize=finalize) - return {'data' : result['data']} - - def readDataAndLock(self, ticket, lockTimeout, container=b''): - result = self.makeRequest('GET','read', ticket=ticket, container=container or None, lock='1', to=lockTimeout) - return {'data' : result['data']} - - - def writeData(self, ticket, data, container=b'', finalize=None): - self.makeRequest('POST','write', ticket=ticket, data=data, container=container or None, finalize=finalize) - return True - - def writeDataAndUnlock(self, ticket, data, container=b'', finalize=None): - self.makeRequest('POST','write', ticket=ticket, data=data, container=container or None, unlock='1', finalize=finalize) - return True - - def lock(self, ticket, lockTimeout, lockid): - self.makeRequest('GET','lock',ticket=ticket, lockid=lockid, to=lockTimeout) - return True - - def unlock(self, ticket, lockid, finalize=None): - self.makeRequest('GET','unlock', ticket=ticket, lockid=lockid, finalize=finalize) - return True - - def getSessionKey(self, ticket, finalize=None): - result = self.makeRequest('GET','key', ticket=ticket, finalize=finalize) - return {'sessionKey' : result['data']} - - def createPFID(self, data=''): - if data: - result = self.makeRequest('POST','sp/create', data=data) - else: - result = self.makeRequest('GET','sp/create') - return {'pfid' : result['data']} - - def removePFID(self, pfid): - self.makeRequest('POST','sp/remove', pfid=pfid) - return True - - def readDataSP(self, pfid): - result = self.makeRequest('GET','sp/read', pfid=pfid) - return {'data' : result['data']} - - def readDataSPandLock(self, pfid, lockTimeout): - result = self.makeRequest('GET','sp/read', pfid=pfid, to=lockTimeout, lock=1) - return {'data' : result['data']} - - def writeDataSP(self, pfid, data): - self.makeRequest('POST','sp/write', pfid=pfid, data=data) - return True - - def writeDataSPandUnlock(self, pfid, data): - self.makeRequest('POST','sp/write', pfid=pfid, data=data, unlock=1) - return True - - def lockSP(self, lockid, lockTimeout): - self.makeRequest('GET','sp/lock',lockid=lockid, to=lockTimeout) - return True - - def unlockSP(self, lockid): - self.makeRequest('GET','sp/unlock',lockid=lockid) - return True - - def getClientKey(self, ticket): - result = self.makeRequest('GET','clientkey',ticket=ticket) - res_dict = {'clientKey' : result['data'], 'ttl' : result['ttl']} - if 'originalTicket' in result: - res_dict['originalTicket'] = result['originalTicket'] - return res_dict - -class WWPassConnectionMT(WWPassConnection): - - def __init__(self, key_file, cert_file, timeout=10, spfe_addr='https://spfe.wwpass.com', ca_file=None, initial_connections=2): - self.Pool = [] - self.key_file = key_file - self.cert_file = cert_file - self.ca_file = ca_file - self.timeout = timeout - self.spfe_addr = spfe_addr - for _ in range(initial_connections): - self.addConnection() - - def addConnection(self, acquired = False): - c = WWPassConnection(self.key_file, self.cert_file, self.timeout, self.spfe_addr, self.ca_file) - c.lock = Lock() - if acquired: - c.lock.acquire() - self.Pool.append(c) - return c - - def getConnection(self): - for conn in (c for c in self.Pool if c.lock.acquire(False)): - return conn - conn=self.addConnection(True) - return conn - - def makeRequest(self, method, command, attempts=3,**paramsDict): - conn = None - try: - conn = self.getConnection() - return conn.makeRequest(method, command, attempts, **paramsDict) - finally: - if conn is not None: - conn.lock.release() - -WWPASSConnection = WWPassConnection -WWPASSConnectionMT = WWPassConnectionMT diff --git a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpassauth.py b/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpassauth.py deleted file mode 100644 index eadaf673378..00000000000 --- a/jans-linux-setup/jans_setup/static/extension/person_authentication/other/wwpass/wwpassauth.py +++ /dev/null @@ -1,289 +0,0 @@ -from io.jans.service.cdi.util import CdiUtil -from io.jans.as.server.security import Identity -from org.gluu.oxauth.model.configuration import AppConfiguration -from io.jans.model.custom.script.type.auth import PersonAuthenticationType -from io.jans.as.server.service import AuthenticationService -from org.xdi.oxauth.service import UserService -from io.jans.util import StringHelper -from io.jans.service import MailService -from org.gluu.oxauth.model.configuration import AppConfiguration - -from jakarta.faces.context import FacesContext - -from com.google.common.io import BaseEncoding - -from urlparse import urlparse - -import jarray -from java.util import Arrays -from java.security import SecureRandom -import java - -from time import time - -from wwpass import WWPassConnection - - -class PersonAuthentication(PersonAuthenticationType): - EMAIL_NONCE_EXPIRATION = 600 # seconds - - def __init__(self, currentTimeMillis): - self.currentTimeMillis = currentTimeMillis - self.user = None - - @staticmethod - def generateNonce(keyLength): - bytes = jarray.zeros(keyLength, "b") - secureRandom = SecureRandom() - secureRandom.nextBytes(bytes) - return BaseEncoding.base64().omitPadding().encode(bytes) - - def init(self, configurationAttributes): - print "WWPASS. Initialization" - self.allow_email_bind = configurationAttributes.get("allow_email_bind").getValue2() if configurationAttributes.containsKey("allow_email_bind") else '' - self.allow_password_bind = configurationAttributes.get("allow_password_bind").getValue2() if configurationAttributes.containsKey("allow_password_bind") else '' - self.allow_passkey_bind = configurationAttributes.get("allow_passkey_bind").getValue2() if configurationAttributes.containsKey("allow_passkey_bind") else '' - self.registration_url = configurationAttributes.get("registration_url").getValue2() if configurationAttributes.containsKey("registration_url") else '' - self.recovery_url = configurationAttributes.get("recovery_url").getValue2() if configurationAttributes.containsKey("recovery_url") else '' - self.wwc = WWPassConnection( - configurationAttributes.get("wwpass_key_file").getValue2(), - configurationAttributes.get("wwpass_crt_file").getValue2()) - self.use_pin = configurationAttributes.get("use_pin").getValue2() if configurationAttributes.containsKey("use_pin") else None - self.auth_type = ('p',) if self.use_pin else () - self.sso_cookie_domain = '.'.join(urlparse(CdiUtil.bean(AppConfiguration).getBaseEndpoint()).netloc.split('.')[-2:]) - sso_cookie_tags = configurationAttributes.get("sso_cookie_tags").getValue2() if configurationAttributes.containsKey("sso_cookie_tags") else None - if sso_cookie_tags: - self.sso_cookie_tags = sso_cookie_tags.split(' ') - else: - self.sso_cookie_tags = [] - print "WWPASS. Initialized successfully" - return True - - def destroy(self, configurationAttributes): - print "WWPASS. Destroy" - return True - - def getApiVersion(self): - return 2 - - def isValidAuthenticationMethod(self, usageType, configurationAttributes): - return True - - def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes): - return None - - def tryFirstLogin(self, puid, userService, authenticationService): # Login user that was just registered via external link - user = userService.getUserByAttribute("oxTrustExternalId", "wwpass:%s"%puid) - if user and authenticationService.authenticate(user.getUserId()): - userService.addUserAttribute(user.getUserId(), "oxExternalUid", "wwpass:%s"%puid) - userService.removeUserAttribute(user.getUserId(),"oxTrustExternalId", "wwpass:%s"%puid) - return True - return False - - def getPuid(self, ticket): - puid = self.wwc.getPUID(ticket, self.auth_type)['puid'] - assert puid #Just in case it's empty or None - return puid - - def authenticateWithWWPass(self, userService, authenticationService, identity, ticket): - puid = self.getPuid(ticket) - user = userService.getUserByAttribute("oxExternalUid", "wwpass:%s"%puid) - if user: - if authenticationService.authenticate(user.getUserId()): - return True - else: - if self.registration_url and self.tryFirstLogin(puid, userService, authenticationService): - return True - identity.setWorkingParameter("puid", puid) - identity.setWorkingParameter("ticket", ticket) - return True - return False - - def bindWWPass(self, requestParameters, userService, authenticationService, identity, ticket): - puid = identity.getWorkingParameter("puid") - email = requestParameters.get('email')[0] if 'email' in requestParameters else None - if not puid: - identity.setWorkingParameter("errors", "WWPass login failed") - return False - if ticket: - puid_new = self.getPuid(ticket) - # Always use the latest PUID when retrying step 2 - identity.setWorkingParameter("puid", puid_new) - if puid == puid_new: - # Registering via external web service - if not self.registration_url: - return False - if self.tryFirstLogin(puid, userService, authenticationService): - identity.setWorkingParameter("puid", None) - return True - else: - if not self.allow_passkey_bind: - return False - # Binding with existing PassKey - user = userService.getUserByAttribute("oxExternalUid", "wwpass:%s"%puid_new) - if user: - if authenticationService.authenticate(user.getUserId()): - userService.addUserAttribute(user.getUserId(), "oxExternalUid", "wwpass:%s"%puid) - identity.setWorkingParameter("puid", None) - return True - identity.setWorkingParameter("errors", "Invalid user") - return False - elif email: - # Binding via email - if not self.allow_email_bind: - return False - email = requestParameters.get('email')[0] if 'email' in requestParameters else None - identity.setWorkingParameter("email", email) - user = userService.getUserByAttribute('mail', email) - if not user: - print("User with email '%s' not found." % email) - return True - nonce = self.generateNonce(33) - mailService = CdiUtil.bean(MailService) - identity.setWorkingParameter("email_nonce", nonce) - identity.setWorkingParameter("email_nonce_exp", str(time() + self.EMAIL_NONCE_EXPIRATION)) - subject = "Bind your WWPass Key" - body = """ -To bind your WWPass Key to your account, copy and paste the following -code into "Email code" field in the login form: -%s -If you haven't requested this operation, you can safely disregard this email. - """ - mailService.sendMail(email, subject, body % nonce) - return True - else: - # Binding via username/password - if not self.allow_password_bind: - return False - puid = identity.getWorkingParameter("puid") - if not puid: - return False - credentials = identity.getCredentials() - user_name = credentials.getUsername() - user_password = credentials.getPassword() - logged_in = False - if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)): - try: - logged_in = authenticationService.authenticate(user_name, user_password) - except Exception as e: - print(e) - if not logged_in: - identity.setWorkingParameter("errors", "Invalid username or password") - return False - user = authenticationService.getAuthenticatedUser() - if not user: - identity.setWorkingParameter("errors", "Invalid user") - return False - userService.addUserAttribute(user_name, "oxExternalUid", "wwpass:%s"%puid) - identity.setWorkingParameter("puid", None) - return True - return False - - def checkEmailNonce(self, requestParameters, userService, authenticationService, identity, ticket): - # Verify email nonce - if not self.allow_email_bind: - identity.setWorkingParameter("email", None) - return False - puid = identity.getWorkingParameter("puid") - if not puid: - return False - nonce = requestParameters.get('code')[0] if 'code' in requestParameters else None - email = identity.getWorkingParameter("email") - proper_nonce = identity.getWorkingParameter("email_nonce") - nonce_expiration = float(identity.getWorkingParameter("email_nonce_exp") or 0.0) - if not nonce or not email or not proper_nonce or not nonce_expiration or nonce_expiration < time() or nonce != proper_nonce: - print("WWPass. Wrong email verification code", nonce,email,proper_nonce,nonce_expiration, time()) - identity.setWorkingParameter("email", None) - identity.setWorkingParameter("errors", "Invalid email or verification code") - return False - user = userService.getUserByAttribute('mail', email) - identity.setWorkingParameter("email", None) - if user: - if authenticationService.authenticate(user.getUserId()): - userService.addUserAttribute(user.getUserId(), "oxExternalUid", "wwpass:%s"%identity.getWorkingParameter("puid")) - identity.setWorkingParameter("puid", None) - return True - print("No user") - return False - - - def doAuthenticate(self, step, requestParameters, userService, authenticationService, identity, ticket): - if step == 1: - return self.authenticateWithWWPass(userService, authenticationService, identity, ticket) - elif step == 2: - return self.bindWWPass(requestParameters, userService, authenticationService, identity, ticket) - elif step == 3: - return self.checkEmailNonce(requestParameters, userService, authenticationService, identity, ticket) - else: - return False - - - def authenticate(self, configurationAttributes, requestParameters, step): - print("WWPass. Authenticate for step %d" %step) - authenticationService = CdiUtil.bean(AuthenticationService) - userService = CdiUtil.bean(UserService) - ticket = requestParameters.get('wwp_ticket')[0] if 'wwp_ticket' in requestParameters else None - identity = CdiUtil.bean(Identity) - identity.setWorkingParameter("errors", "") - result = self.doAuthenticate(step, requestParameters, userService, authenticationService, identity, ticket) - if result and self.sso_cookie_tags: - externalContext = CdiUtil.bean(FacesContext).getExternalContext() - for tag in self.sso_cookie_tags: - externalContext.addResponseCookie("sso_magic_%s"%tag, "auth", {"path":"/", "domain":self.sso_cookie_domain, "maxAge": CdiUtil.bean(AppConfiguration).getSessionIdUnusedLifetime()}) - return result - - def prepareForStep(self, configurationAttributes, requestParameters, step): - identity = CdiUtil.bean(Identity) - identity.setWorkingParameter("sessionLifetime",CdiUtil.bean(AppConfiguration).getSessionIdUnauthenticatedUnusedLifetime()) - identity.setWorkingParameter("use_pin", bool(self.use_pin)) - print("PrepareForStep %s" % step) - if (step == 1): - return True - elif (step == 2): - identity.setWorkingParameter("registration_url", self.registration_url) - identity.setWorkingParameter("recovery_url", self.recovery_url) - identity.setWorkingParameter("allow_email_bind", self.allow_email_bind) - identity.setWorkingParameter("allow_password_bind", self.allow_password_bind) - identity.setWorkingParameter("allow_passkey_bind", self.allow_passkey_bind) - print("WWPASS. Errors:%s" % identity.getWorkingParameter("errors")) - return True - elif (step == 3): - return True - return False - - def getExtraParametersForStep(self, configurationAttributes, step): - if step == 3: - return Arrays.asList("puid", "email", "email_nonce", "email_nonce_exp", "sessionLifetime") - return Arrays.asList("puid", "ticket", "use_pin", "errors", "email", "sessionLifetime") - - def getCountAuthenticationSteps(self, configurationAttributes): - identity = CdiUtil.bean(Identity) - if not identity.isSetWorkingParameter("puid"): - return 1 - if not identity.isSetWorkingParameter("email"): - return 2 - return 3 - - def getPageForStep(self, configurationAttributes, step): - if step == 1: - return "/auth/wwpass/wwpass.xhtml" - if step == 2: - return "/auth/wwpass/wwpassbind.xhtml" - return "/auth/wwpass/checkemail.xhtml" - - def logout(self, configurationAttributes, requestParameters): - print("WWPASS. Logout") - # This is not called. Probably bug in Gluu - # externalContext = CdiUtil.bean(FacesContext).getExternalContext() - # externalContext.addResponseCookie("sso_magic", "auth", {"path":"/", "domain":self.sso_cookie_domain, "maxAge": 0}) - return True - - def getNextStep(self, configurationAttributes, requestParameters, step): - # If user did not pass this step, change the step to previous one - identity = CdiUtil.bean(Identity) - puid = identity.getWorkingParameter("puid") - email = identity.getWorkingParameter("email") - print ("WWPass getNextStep for step %d, email: %s" % (step, email)) - if puid and not email and step != 1: - return 2 - return -1