Freja eID management - delegated

This guide will give you a rough instruction on how to configure the Freja eID management.

The usecase is when a user will enroll or revoke in a deligated scenario.

This video will show you how this works.

Prereqs

  • Trust to SAML IdP which will be used to protect this app
  • Frejaeid keystore uploaded to PAS
  • LDAP server configured with sAMAccountName as userid and employeeID for personnr
  • Trust to Freja backend HTTPS/TLS

Management App

Templates

Download and unzip the templates from this zip-file and place them in PAS-FOLDER\overlay\auth-http\files\templates\Freja-mgmt

Authenticators

Add the block below to the Auhentication - HTTP bucket.

Replace these strings before commiting:

Value to replace
Comment
Replace-Value-with-DNS-For-Your-Server
The DNS-name of your server, ex: pas.company.org
Replace-Value-with-EntityID-For-Your-IDP
The EntityID from the IdP protecting this app.
{
	"alias": "frejamgmt",
	"name": "Registration",
	"id": "frejamgmt",
	"configuration": {
		"stages": [{
				"pipeid": "frejamgmt-username",
				"template": "C:\\Program Files\\PhenixID\\Server\\overlay\\auth-http\\files\\templates\\Freja-mgmt\\freja-mgmt-1",
				"sessionValues": [
					"roles",
					"adminuser"
				],
				"translation": [
					"phxverify.messages.information.title",
					"phxverify.messages.information.searchuser",
					"phxverify.messages.username",
					"phxverify.messages.querybox",
					"phxverify.messages.or",
					"phxverify.messages.logout"
				],
				"templateVariables": {
					"searchmethods": [{
							"type": "username",
							"title": "phxverify.messages.username"
						},
						{
							"type": "mail",
							"title": "phxverify.messages.mail"
						},
						{
							"type": "mobile",
							"title": "phxverify.messages.mobile"
						}
					],
					"settings": {
						"sp_url": "/frejamgmt/authenticate/frejamgmtsp/"
					}
				},
				"errorTranslation": [{
						"key": "User does not exist",
						"value": "phxverify.error.usernotexist"
					},
					{
						"key": "Multiple users found",
						"value": "phxverify.error.multipleusersfound"
					},
					{
						"key": "Login failed",
						"value": "phxverify.error.loginfailed"
					}
				]
			},
			{
				"pipeid": "frejamgmt-action",
				"template": "C:\\Program Files\\PhenixID\\Server\\overlay\\auth-http\\files\\templates\\Freja-mgmt\\freja-mgmt-2",
				"templateVariables": {
					"useBid": "",
					"methods": [{
							"type": "activate",
							"title": "Aktivera Freja OrgID"
						},
						{
							"type": "inactivate",
							"title": "Radera Freja OrgID"
						}
					]
				},
				"sessionValues": [
					"phxverify-disabled-token",
					"phxverify-disabled-sms",
					"phxverify-disabled-ot",
					"phxverify-disabled-mail",
					"phxverify-disabled-bid",
					"givenname",
					"sn",
					"mobile",
					"username",
					"mail",
					"roles",
					"adminuser",
					"pnr",
					"currentFrejaUser"
				],
				"translation": [
					"phxverify.messages.information.title",
					"phxverify.messages.username",
					"phxverify.messages.givenname",
					"phxverify.messages.snname",
					"phxverify.messages.mobile",
					"phxverify.messages.mail",
					"phxverify.messages.information.choose_method",
					"phxverify.messages.cancel",
					"phxverify.messages.logout",
					"phxverify.messages.bid"
				],
				"errorTranslation": [

					{
						"key": "User does not exist",
						"value": "phxverify.error.usernotexist"
					},
					{
						"key": "Multiple users found",
						"value": "phxverify.error.multipleusersfound"
					},
					{
						"key": "Login failed",
						"value": "phxverify.error.loginfailed"
					}
				]
			},
			{
				"pipeid": "frejamgmt-complete",
				"template": "C:\\Program Files\\PhenixID\\Server\\overlay\\auth-http\\files\\templates\\Freja-mgmt\\freja-mgmt-3",
				"templateVariables": {
					"useBid": ""
				},
				"translation": [
					"phxverify.messages.information.title",
					"phxverify.messages.username",
					"phxverify.messages.enterotp",
					"phxverify.messages.givenname",
					"phxverify.messages.snname",
					"phxverify.messages.mobile",
					"phxverify.messages.mail",
					"phxverify.messages.ot",
					"phxverify.messages.otstatus",
					"phxverify.messages.sms",
					"phxverify.messages.mail",
					"phxverify.messages.pp",
					"phxverify.messages.verify",
					"phxverify.messages.information.verifyotp",
					"phxverify.messages.information.otpending",
					"phxverify.messages.information.bidpending",
					"phxverify.messages.information.ot_timedout",
					"phxverify.messages.information.bid_timedout",
					"phxverify.messages.cancel",
					"phxverify.messages.logout",
					"phxverify.messages.bid"
				],
				"sessionValues": [
					"phxverify-disabled-token",
					"phxverify-disabled-sms",
					"phxverify-disabled-ot",
					"phxverify-disabled-mail",
					"phxverify-disabled-bid",
					"givenname",
					"sn",
					"mobile",
					"username",
					"mail",
					"roles",
					"phxverify-verifyotp",
					"phxverify-otpending",
					"phxverify-bidpending",
					"adminuser",
					"pnr",
					"activate",
					"inactivate"
				],
				"errorTranslation": []
			}
		]
	}
}, {
	"id": "frejamgmtsp",
	"alias": "frejamgmtsp",
	"name": "SAMLServiceProviderAuthN",
	"displayName": "frejamgmtsp IdP",
	"configuration": {
		"successURL": "/frejamgmt/authenticate/frejamgmt/",
		"sp": "https://Replace-Value-with-DNS-For-Your-Server/frejamgmt",
		"pipeID": "FrejaMgmtSPPipe",
		"targetIDP": "Replace-Value-with-EntityID-For-Your-IDP",
		"acsUrl": "https://Replace-Value-with-DNS-For-Your-Server/frejamgmt/authenticate/frejamgmtsp",
		"entityID": "https://Replace-Value-with-DNS-For-Your-Server/frejamgmt"
	}
}

SAML SP

Add the block below to the SAML 2 Service provides bucket.

Replace these strings before commiting:

Value to replace
Comment
Replace-Value-with-DNS-For-Your-Server
The DNS-name of your server, ex: pas.company.org
Replace-Value-with-ID-of-SAML-Signing-Keystore
The ID of the keystore used to sign SAML-tokens
{
	"id": "https://Replace-Value-with-DNS-For-Your-Server/frejamgmt",
	"keystoreSign": "Replace-Value-with-ID-of-SAML-Signing-Keystore",
	"keystoreEncrypt": "Replace-Value-with-ID-of-SAML-Signing-Keystore",
	"entityID": "https://Replace-Value-with-DNS-For-Your-Server/frejamgmt"
}

Pipes

Add the block below to the Pipes bucket.

Replace these strings before commiting:

Value to replace
Comment
Replace-Value-With-Organizaion-Name
Your organization name. This value will be displayed for the user when authenticating, ex Our Company.
Replace-With-Friendly-Name-Of-UserID
The friendly name of the userid. This value will be displayed for the user when authenticating, ex: AnvändarID.
Replace-Value-with-ID-of-Freja-Keystore
The id of the keystore previously uploaded to PAS for communication with Freja Backend
{
		"id": "frejamgmt-username",
		"valves": [
			{
				"name": "SessionLoadValve",
				"config": {
					"id": "{{request.session_id}}"
				}
			},
			{
				"name": "FlowFailValve",
				"config": {
					"message": "Login failed",
					"skip_if_expr": "request.get('authenticatedrequest').equals('true')"
				}
			},
			{
				"name": "SessionPropertyRemoveValve",
				"config": {
					"name": "currentFrejaUser,activate,inactivate,username,generated_otp,phxverify-verifyotp,ot_verify,phxverify-otpending,phxverify-bidpending,phxverify-disabled-bid,phxverify-newstatus,phxverify-disabled-sms,phxverify-disabled-mail,phxverify-disabled-token,phxverify-disabled-ot,givenname,OATH,PKI,username,mobile,sn,mail,pnr,pnrsub"
				}
			},
			{
				"name": "LDAPSearchValve",
				"config": {
					"connection_ref": "Replace-Value-with-ID-of-LDAP-Connection",
					"base_dn": "Replace-Value-with-LDAP-BaseDN",
					"scope": "SUB",
					"size_limit": "0",
					"filter_template": "sAMAccountName={{request.username}}",
					"attributes": "mobile,givenName,sn,mail,employeeID",
					"exec_if_expr": "request.get('username')!=null"
				}
			},
			{
				"name": "LDAPSearchValve",
				"config": {
					"connection_ref": "Replace-Value-with-ID-of-LDAP-Connection",
					"base_dn": "Replace-Value-with-LDAP-BaseDN",
					"scope": "SUB",
					"size_limit": "0",
					"filter_template": "mail={{request.mail}}",
					"attributes": "mobile,givenName,sn,mail,sAMAccountName,employeeID",
					"exec_if_expr": "request.get('mail')!=null"
				}
			},
			{
				"name": "LDAPSearchValve",
				"config": {
					"connection_ref": "Replace-Value-with-ID-of-LDAP-Connection",
					"base_dn": "Replace-Value-with-LDAP-BaseDN",
					"scope": "SUB",
					"size_limit": "0",
					"filter_template": "mobile={{request.mobile}}",
					"attributes": "mobile,givenName,sn,mail,sAMAccountName,employeeID",
					"exec_if_expr": "request.get('mobile')!=null"
				}
			},
			{
				"name": "FlowFailValve",
				"config": {
					"message": "User does not exist",
					"exec_if_expr": "flow.items().isEmpty()"
				}
			},
			{
				"name": "FlowFailValve",
				"config": {
					"message": "Multiple users found",
					"skip_if_expr": "flow.isSingle()"
				}
			},
			{
				"config": {
					"name": "username",
					"value": "{{request.username}}",
					"exec_if_expr": "request.get('username')!=null"
				},
				"name": "SessionPropertyAddValve"
			},
			{
				"config": {
					"name": "username",
					"value": "{{item.sAMAccountName}}",
					"exec_if_expr": "request.get('mail')!=null || request.get('mobile')!=null"
				},
				"name": "SessionPropertyAddValve"
			},
			{
				"name": "GetTokenExistsValve",
				"config": {
					"username_attribute": "{{session.username}}",
					"token_type": "OATH",
					"get_value_attribute_key": "OATH"
				}
			},
			{
				"name": "GetTokenExistsValve",
				"config": {
					"username_attribute": "{{session.username}}",
					"token_type": "PKI",
					"get_value_attribute_key": "PKI"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "OATH",
					"value": "{{item.OATH}}"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "PKI",
					"value": "{{item.PKI}}"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "mobile",
					"value": "{{item.mobile}}"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"dest_id": "{{session.pki_user}}",
					"name": "givenname",
					"value": "{{item.givenName}}"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "sn",
					"value": "{{item.sn}}"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "mail",
					"value": "{{item.mail}}"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "pnr",
					"value": "{{item.employeeID}}"
				}
			},
			{
				"name": "PropertyAddValve",
				"config": {
					"name": "pnr2sub",
					"value": "{{item.employeeID}}"
				}
			},
			{
				"name": "PropertySubstringValve",
				"config": {
					"source": "pnr2sub",
					"end_index": "8",
					"begin_index": "0",
					"exec_if_expr": "request.get('employeeID')!=null"
				}
			},
			{
				"config": {
					"name": "pnrsub",
					"value": "{{item.pnr2sub}}xxxx"
				},
				"name": "SessionPropertyAddValve"
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "phxverify-disabled-bid",
					"value": "disabled",
					"exec_if_expr": "",
					"skip_if_expr": "flow.items().get(0).containsProperty('employeeID')"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "phxverify-disabled-sms",
					"value": "disabled",
					"exec_if_expr": "",
					"skip_if_expr": "flow.items().get(0).containsProperty('mobile')"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "phxverify-disabled-mail",
					"value": "disabled",
					"exec_if_expr": "",
					"skip_if_expr": "flow.items().get(0).containsProperty('mail')"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "phxverify-disabled-token",
					"value": "disabled",
					"exec_if_expr": "flow.property('OATH').equals('false')"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "phxverify-disabled-ot",
					"value": "disabled",
					"exec_if_expr": "flow.property('PKI').equals('false')"
				}
			},
			{
				"name": "HttpPostRequestValve",
				"config": {
					"url": "https://services.prod.frejaeid.com/organisation/management/orgId/1.0/users/getAll",
					"body": "{{item.body}}",
					"http_crypto_protocol": "TLS",
					"trust_all_certs": "true",
					"keystore": "Replace-Value-with-ID-of-Freja-Keystore"
				}
			},
			{
				"name": "SessionPropertyReplaceValve",
				"config": {
					"name": "currentFrejaUser",
					"value": "true",
					"exec_if_expr": "flow.property('http_response_body').contains(session.get('username'))"
				}
			},
			{
				"name": "SessionPersistValve",
				"config": {}
			}
		]
	},{
		"id": "frejamgmt-action",
		"valves": [
			{
				"name": "SessionLoadValve",
				"config": {
					"id": "{{request.session_id}}"
				}
			},
			{
				"name": "SessionPropertyRemoveValve",
				"config": {
					"name": "ot_verify, phxverify-otpending,phxverify-bidpending,phxverify-verifyotp,generated_otp,transactionID,activate,inactivate"
				}
			},
			{
				"name": "ItemCreateValve",
				"config": {
					"dest_id": "{{request.session_id}}"
				}
			},
			{
				"name": "PropertyAddValve",
				"enabled": "true",
				"config": {
					"name": "userInfo",
					"value": "{\"country\":\"SE\",\"ssn\":\"{{session.pnr}}\"}",
					"splitter": "@"
				}
			},
			{
				"name": "PropertyStringBase64EncoderValve",
				"config": {
					"source": "userInfo",
					"dest": "userInfob64"
				}
			},
			{
				"name": "PropertyAddValve",
				"config": {
					"name": "initAddOrganisationIdRequest",
					"value": "{ \"userInfoType\": \"SSN\", \"userInfo\": \"{{item.userInfob64}}\", \"organisationId\": { \"title\": \"Replace-Value-With-Organizaion-Name\", \"identifierName\": \"Replace-With-Friendly-Name-Of-UserID\", \"identifier\": \"{{session.username}}\" } }",
					"splitter": "@"
				}
			},
			{
				"name": "PropertyStringBase64EncoderValve",
				"config": {
					"source": "initAddOrganisationIdRequest",
					"dest": "initAddOrganisationIdRequestb64",
					"exec_if_expr": "request.getOrDefault('type','').equals('activate')"
				}
			},
			{
				"name": "PropertyAddValve",
				"config": {
					"name": "body",
					"value": "initAddOrganisationIdRequest={{item.initAddOrganisationIdRequestb64}}",
					"splitter": "@",
					"exec_if_expr": "request.getOrDefault('type','').equals('activate')"
				}
			},
			{
				"name": "PropertyAddValve",
				"config": {
					"name": "deleteOrganisationIdRequest",
					"value": "{\"identifier\":\"{{session.username}}\"}",
					"splitter": "@"
				}
			},
			{
				"name": "PropertyStringBase64EncoderValve",
				"config": {
					"source": "deleteOrganisationIdRequest",
					"dest": "deleteOrganisationIdRequestb64",
					"exec_if_expr": "request.getOrDefault('type','').equals('inactivate')"
				}
			},
			{
				"name": "PropertyAddValve",
				"config": {
					"name": "body",
					"value": "deleteOrganisationIdRequest={{item.deleteOrganisationIdRequestb64}}",
					"splitter": "@",
					"exec_if_expr": "request.getOrDefault('type','').equals('inactivate')"
				}
			},
			{
				"name": "HttpPostRequestValve",
				"config": {
					"url": "https://services.prod.frejaeid.com/organisation/management/orgId/1.0/initAdd",
					"body": "{{item.body}}",
					"http_crypto_protocol": "TLS",
					"trust_all_certs": "true",
					"keystore": "Replace-Value-with-ID-of-Freja-Keystore",
					"exec_if_expr": "request.getOrDefault('type','').equals('activate')"
				}
			},
			{
				"name": "HttpPostRequestValve",
				"config": {
					"url": "https://services.prod.frejaeid.com/organisation/management/orgId/1.0/delete",
					"body": "{{item.body}}",
					"http_crypto_protocol": "TLS",
					"trust_all_certs": "true",
					"keystore": "Replace-Value-with-ID-of-Freja-Keystore",
					"exec_if_expr": "request.getOrDefault('type','').equals('inactivate')"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "phxverify-verifyotp",
					"value": "true",
					"exec_if_expr": "request.get('type') != null && (request.get('type').contains('sms') || request.get('type').contains('token') || request.get('type').contains('mail'))"
				}
			},
			{
				"name": "ItemMergeValve",
				"config": {
					"dest_id": "{{request.session_id}}"
				}
			},
			{
				"name": "SessionPropertyRemoveValve",
				"config": {
					"name": "currentFrejaUser"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "activate",
					"value": "true",
					"exec_if_expr": "request.getOrDefault('type','').equals('activate')"
				}
			},
			{
				"name": "SessionPropertyAddValve",
				"config": {
					"name": "inactivate",
					"value": "true",
					"exec_if_expr": "request.getOrDefault('type','').equals('inactivate')"
				}
			},
			{
				"name": "SessionPersistValve",
				"config": {}
			}
		]
	}, {
	"id": "FrejaMgmtSPPipe",
	"valves": [
		{
			"name": "AssertionConsumer",
			"config": {}
		},
		{
			"name": "FlowFailValve",
			"config": {
				"message": "User does not exist",
				"exec_if_expr": "flow.items().isEmpty()"
			}
		}
	]
}