FullCount utilizes the OpenId Connect (ODIC) protocol to
authenticate users from external identity providers (IDP) into the Back Office.
Documentation we can provide to the customer about the process can be found
in T:\TechServices\Projects\Integration\SSO\FullCount SSO.pdf
Information for any new SSO provider needs to be added to
the identity_providers table.
provider_name
- The name of the customer or identity provider. No spaces allowed.
client_id
- Provided by the customer. Id that uniquely identifies FullCount's
application to the customer's IDP.
client_secret
- Provided by the customer. Secret to authenticate FullCount to the
customer's IDP.
access_token_url
- Provided by the customer. Endpoint of the customer's IDP that provides
the JWT token.
authorization_url
- Provided by the customer. Endpoint of the customer's IDP that provides
the auth code to FullCount's redirect URL.
user_info_url
- Provided by the customer only if there is no id_token on the access
token response. Endpoint of the customer's IDP to fetch info about the
user.
token_info_url
- ???
security_group_name
- Provided by the customer. We can validate that the JWT from the
customer's IDP contains a specific security group. But they should just be
able to check that on their side before even returning the JWT. So this
shouldn't really be used.
scope
- Set to BO for Back Office SSO
jwt_issuer
- Provided by the customer. The 'iss' attribute of the JWT so we can
verify. Optional.
custom_flow
- Set to 'N' if this SSO uses our generic code for SSO. Set to 'Y' if we
need to write classes specific to the SSO implementation.
oauth_scopes
- Provided by the customer. List of comma delimited scopes to include in
the authorization request to the customer's IDP (ex: email,openid).
Generic SSO
When a customer's identity provider conforms to the OIDC
protocol, we should be able to create an SSO flow with minimal effort. Create a
new record in the identity_providers table with the information above. This
information is loaded into properties in the Back Office application at
startup, so a restart is needed for the new record to be included.
Details
Each record from the identity_providers table is split and
loaded as properties in the BackofficeProperties class. For example for the
record with a provider_name of Masonic, properties are created for
Masonic.clientId, Masonic.clientSecret, Masonic.registeredRedirectUrl, etc. A
separate property called GenericSSOProviders stores a comma delimited list of
each provider where custom_flow is set to 'N'.
The BackofficeSecurityContext class creates a Filter for
each provider in GenericSSOProviders, using our custom
OAuthSSOFilterBuilder class. This class may need to be adjusted occassionally
to accomodate small differences in IDP's OIDC implementations, but needs to
remain generic to continue to support existing generic flows. If an IDP
requires significant accomodation, a custom flow should be used instead.
Custom SSO
Before an effort in 2025 to genericize Back Office SSO,
FullCount started out by making custom SSO flows for each identity provider. We
still might need to do so for cases that don't fit the OIDC flow or for other
reasons we cannot predict. Information is still entered as normal into the
identity_providers table, with custom_flow set to 'Y'.
A FullCount developer will then need to write custom code to
accomodate the flow which will depend on case. At a minimum, a new Filter will
have to be created in the BackofficeSecurityContext class and added to the
ssoFilter() method. When creating a custom Filter for a new IDP, try to extend
the OAuthSSOFilterBuilder class and reuse as much as possible.
Testing
The systems team has set up an Azure app registration in our
own Azure environment to simulate a vendor identity provider. The registration
is called
Test Back Office SSO. If the client secret gets lost or
expires, just have systems generate a new one. For the full SSO process to
work, the user must have a unique email in our user_profile table.
When possible, FullCount tries to utilize the OpenId Connect
(ODIC) protocol to authenticate users from external identity providers (IDP)
into Engage. Documentation we can provide to the customer about the process can
be found in T:\TechServices\Projects\Integration\SSO\FullCount SSO.pdf
Information for any new SSO provider needs to be added to
the identity_providers table.
provider_name
- The name of the customer or identity provider. No spaces allowed.
client_id
- Provided by the customer. Id that uniquely identifies FullCount's
application to the customer's IDP.
client_secret
- Provided by the customer. Secret to authenticate FullCount to the
customer's IDP.
access_token_url
- Provided by the customer. Endpoint of the customer's IDP that provides
the JWT token.
authorization_url
- Provided by the customer. Endpoint of the customer's IDP that provides
the auth code to FullCount's redirect URL.
user_info_url
- Provided by the customer only if there is no id_token on the access
token response. Endpoint of the customer's IDP to fetch info about the
user.
token_info_url
- ???
security_group_name
- Provided by the customer. We can validate that the JWT from the
customer's IDP contains a specific security group. But they should just be
able to check that on their side before even returning the JWT. So this
shouldn't really be used.
scope
- Set to RP for Engage SSO (stands for resident portal)
jwt_issuer
- Provided by the customer. The 'iss' attribute of the JWT so we can
verify. Optional.
custom_flow
- Set to 'N' if this SSO uses our generic code for SSO. Set to 'Y' if we
need to write classes specific to the SSO implementation.
oauth_scopes
- Provided by the customer. List of comma delimited scopes to include in
the authorization request to the customer's IDP (ex: email,openid).
Generic SSO
When a customer's identity provider conforms to the OIDC
protocol, we should be able to create an SSO flow with minimal effort. Create a
new record in the identity_providers table with the information above. This
information is loaded into properties in the Back Office application at
startup, so a restart is needed for the new record to be included.
IDP Token Field Mappings
Often times, FullCount cannot rely on email address to match
residents between third party resident engagement platforms and our resident
records. To support multiple matching strategies, there exists the
idp_token_field_mappings table in our database to tie data fields in our
database to data fields in the identity provider's JWT token. It has the
following columns:
identity_provider_id
- The identity provider the mapping is associated with
resident_field_lable
- The name of a column in FullCount's residents table that we want to use
to match customers
idp_token_field_label
- The name of an attribute in the identity provider's authorization token
that we want to use to match customers
priority
- The order to perform a match in the case there are multiple records for
this identity provider
Take the following idp_token_field_mapping records as an
example. In this case, our SSO process will first try to match the 'email'
field in the identity provider's JWT token to the email field in our residents
table. If it does not find a unique match, it will then try to match the
'first_name', 'last_name', and 'apartment_no' fields in the identity provider's
JWT token to the first_name, last_name, and apartment fields in our residents
table respectively. If it does not find a match for all three of those pieces
of data, then it will return an error. If there is one unique match at any
priority level, the SSO process will log that resident in.
|
identity_provider_id
|
resident_field_lable
|
idp_token_field_label
|
priority
|
|
362
|
EMAIL
|
email
|
1
|
|
362
|
FIRST_NAME
|
first_name
|
2
|
|
362
|
LAST_NAME
|
last_name
|
2
|
|
362
|
APARTMENT
|
apartment_no
|
2
|
Details
Each record from the identity_providers table is split and
loaded as properties in the AuthorizationProperties class. For example for
the record with a provider_name of Catie, properties are created for
Catie.clientId, Catie.clientSecret, Catie.registeredRedirectUrl, etc. A
separate property called GenericSSOProviders stores a comma delimited list of
each provider where custom_flow is set to 'N'.
The SecurityConfiguration class creates a Filter for each
provider in GenericSSOProviders, using our custom OAuthSSOFilterBuilder
class. This class may need to be adjusted occassionally to accomodate small
differences in IDP's OIDC implementations, but needs to remain generic to
continue to support existing generic flows. If an IDP requires significant
accomodation, a custom flow should be used instead.
Custom SSO
Before an effort in 2025 to genericize Engage SSO, FullCount
started out by making custom SSO flows for each identity provider. We still
might need to do so for cases that don't fit the OIDC flow or for other reasons
we cannot predict. Information is still entered as normal into the
identity_providers table, with custom_flow set to 'Y'.
A FullCount developer will then need to write custom code to
accomodate the flow which will depend on case. At a minimum, a new Filter will
have to be created in the SecurityConfiguration class and added to the
ssoFilter() method. When creating a custom Filter for a new IDP, try to extend
the OAuthSSOFilterBuilder class and reuse as much as possible.
Testing
The systems team has set up an Azure app registration in our
own Azure environment to simulate a vendor identity provider. The registration
is called
Test Generic Engage SSO. If the client secret gets lost or
expires, just have systems generate a new one.