A .NET console application that can be run on a schedule or as a scheduled task that will synchronize users and groups between Azure Active Directory and Onspring making Azure Active Directory the system of record.
Note: This is an unofficial Onspring integration. It was not built in consultation with Onspring Technologies LLC.
- Overview
- Requirements
- Installation
- Onspring Setup
- Azure Active Directory Setup
- Configuration
- Options
- Output
- Limitations
- License
- Inspiration
Many Onspring customers who utilize the Onspring platform choose to leverage Onspring's existing SSO integration for authentication. This integration allows customers to setup a single sign-on experience for their users using their existing identity management provider. As part of this existing integration Onspring supports accepting claims for the user's username, email address, first name, last name, and optionally groups.
It also allows for just-in-time provisioning of users and groups if they are not already present in Onspring. This integration also updates the user's username, email address, first name, last name, and groups in Onspring upon each login if they change in the identity management provider between logins. Many customers utilize this integration with Azure Active Directory (AAD) as their identity management provider
However the existing SSO integration doesn't allow customers to centrally manage their users and groups in Onspring through Azure Active Directory and keep the two systems in sync using Azure Active Directory as the system of record. Nor allow them to leverage any existing user and group data or access models built in Azure Active Directory to also manage access in Onspring.
The OnspringAzureADSyncer app is meant to help fill this gap and provide Onspring customers with a way to sync Azure AD groups and users to Onspring.
âś… Allow Azure Active Directory to serve as the system of record for managing users and groups.
âś… Synchronize all users and groups in Azure Active Directory with Onspring.
âś… Activate and deactivate Onspring users based on group membership in specific Azure Active Directory groups.
âś… Map Azure Active Directory user properties to Onspring user fields.
âś… Map Azure Active Directory group properties to Onspring group fields.
- You must have an Onspring instance.
- You must have an Onspring API Key that has the following permissions to the following apps:
Users
- Create
- Read
- Update
Groups
- Create
- Read
- Update
- You must have an Azure Active Directory tenant.
- You must have an Azure Active Directory application registered in your Azure Active Directory tenant.
- The application must have the following permissions:
Group.Read.All
User.Read.All
- The application must have the following permissions:
The app is published as a release on GitHub. You can download the latest release from the releases page. It is published as a single executable file for the following operating systems:
- win-x64
- linux-x64
- ox-x64 (Minimum OS version is macOS 10.12 Sierra)
- Note after downloading the executable you may need to run
chmod +x
to give the executable execute permissions on your machine. - Note after downloading the executable you may need to provide permission for the application to run via the your systems settings.
- Note after downloading the executable you may need to run
You are also welcome to clone this repository and run the app using the .NET 7 tooling and runtime. As well as modify the app further for your specific needs.
In order to configure the app you will need to perform some setup in Onspring to acquire the following required configuration values:
BaseUrl
ApiKey
UsersAppId
GroupsAppId
The BaseUrl
is the base url for the Onspring API. Currently this will always be https://api.onspring.com
. It does not matter if you are using the app with a Development
, Test
, or Production
instance.
This app makes use of version 2 of the Onspring API. Therefore you will need an API Key to be able to utilize the app. API keys may be obtained by an Onspring user with permissions to at least read API Keys for your instance, using the following instructions:
- Within Onspring, navigate to /Admin/Security/ApiKey.
- On the list page, add a new API Key (requires Create permissions) or click an existing API Key to view its details.
- On the details page for an API Key, click on the Developer Information tab.
- Copy the X-ApiKey Header value from this section.
Important:
- An API Key must have a status of Enabled in order to be used.
- Each API Key must have an assigned Role. This role controls the permissions for requests that are made by this tool to retrieve files from fields on records in an app. If the API Key does not have sufficient permissions the attachment will not be downloaded.
You can think of any API Key as another user in your Onspring instance and therefore it is subject to all the same permission considerations as any other user when it comes to it's ability to access a file. The API Key you use with this tool need to have all the correct permissions within your instance to access the record where a file is held and the field where the file is held. Things to think about in this context are role permissions
, content security
, and field security
.
This app uses version 2 of the Onspring API to sync groups and users. Currently this version of the Onspring API does not provide any endpoints to perform bulk operations.
This app will make a number of api requests to Onspring in order to...
- collect all the fields in each app
- look up if list values need to be created
- create list values
- look up whether a group or user exists
- create or update groups or users
The total number of requests will vary depending on the number of users and groups being synced as well as the mappings you've configured.
This all being shared because it is important you take into consideration the number of Groups and Users you are planning to sync with Onspring. If the quantity is quite considerable I'd encourage you to consult with your Onspring representative to understand what if any limits there are to your usage of the Onspring API.
The app needs to know the App Id
for the Users
and Groups
apps in your Onspring instance. You can find the App Id
for each app by navigating to the app's admin panel in Onspring and looking at the url. The App Id
is the number at the end of the url.
For example, if you are looking at the Users
app in Onspring and the url is https://myinstance.onspring.com/Admin/App/1
then the App Id
is 1
.
You can also find the AppId
for each app by using the API Key
you created to call the /Apps
endpoint of the Onspring API. This swagger page can be useful for this type of exploratory call.
In order to provide the app with the proper permissions to sync your Azure Active Directory groups and users you will need to setup a new application registration within Azure Active Directory. The following steps can be followed to register the app and get the necessary Tenant Id
, Client Id
, and Client Secret
.
- Go to Azure Active Directory and select
App Registrations
from the left hand menu. - Click
New Registration
. - Enter a name for the app and select
Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)
for the supported account types. - Leave the
Redirect URI
blank. - Click
Register
. - Go to the
API Permissions
section and clickAdd a permission
. - Select
Microsoft Graph
and thenApplication permissions
. - Select the following permissions:
Group.Read.All
User.Read.All
- Click
Add permissions
. - Click
Grant admin consent for <your tenant name>
. - Go to the
Certificates & secrets
section and clickNew client secret
. - Enter a description for the secret and select an expiry time. Click
Add
. - Copy the
Tenant Id
,Client Id
, andClient Secret
values from theOverview
section of the app registration.
The app is configured via a JSON file. You will need to pass the path to the configuration file using the configuration option --config
or -c
. If the config file is not specified the app will not run. See below for an example:
./OnspringAzureADSyncer -c /path/to/config.json
The configuration file needs to have the following format and properties set:
{
"Settings": {
"Onspring": {
"BaseUrl": "https://api.onspring.com",
"ApiKey": "000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000",
"UsersAppId": 1,
"GroupsAppId": 1
},
"Azure": {
"TenantId": "00000000-0000-0000-0000-000000000000",
"ClientId": "0a000aa0-1b11-2222-3c33-444444d44d44",
"ClientSecret": "00000~00000--000000000-00000000000000000"
}
}
}
Note: You can see an example of a complete configuration file in the exampleconfig.json file in this repository.
The app will map the following properties from Azure Active Directory to Onspring by default:
Azure Active Directory Property | Onspring Group Field |
---|---|
id |
Name |
description |
Description |
Note: The id
property is used as the Name
field in Onspring because the Name
field is required and the id
property is guaranteed to be unique.
Note: The id
property to Name
field mapping cannot be changed or overwritten.
Azure Active Directory Property | Onspring User Field |
---|---|
userPrincipalName |
Username |
givenName |
First Name |
surname |
Last Name |
mail |
Email Address |
memberOf |
Groups |
Note: The memberOf
property to Groups
field mapping cannot be changed or overwritten.
Note: The Onspring Users Status
field is not mapped and cannot be mapped to an Azure property. However it will be set by the app for each user. The app determines what value (Active or Inactive) this field is set to based upon whether the user is a member of a specified OnspringActiveGroup and is Enabled
in Azure Active Directory.
The app can be configured to enable activating and deactivating users in Onspring based upon membership to specific Azure Active Directory groups by adding a property to the Azure
object called OnspringActiveGroups
that contains an array of object ids for each group that contains users who should be active in Onspring. See below for an example:
{
...,
"Azure": {
"TenantId": "00000000-0000-0000-0000-000000000000",
"ClientId": "0a000aa0-1b11-2222-3c33-444444d44d44",
"ClientSecret": "00000~00000--000000000-00000000000000000",
"OnspringActiveGroups": [
"00000000-0000-0000-0000-000000000000",
"00000000-0000-0000-0000-000000000000"
]
},
...
}
When this property is set the app will set Onspring users to active if they are a member of one of these groups and their account is Enabled
in Azure Active Directory.
The app can be configured to map custom properties from Azure Active Directory to Onspring by adding the GroupsFieldMappings
and UsersFieldMappings
properties to the Settings
object. The properties in these objects should be the id of the field in Onspring and the name of the property for the Azure resource whose value you want to map to that field in Onspring. See below for an example:
{
...,
"GroupsFieldMappings": {
"4933": "displayName"
},
"UsersFieldMappings": {
"9": "streetAddress",
"2": "city",
"4934": "state",
"11": "postalCode"
},
...
}
This does support mapping Azure properties to Onspring fields that are and are not included in the default mappings. In addition you can map a single Azure property to multiple Onspring fields if you need to. As noted in the Default Mappings section there are some fields that cannot be mapped or whose mappings can not be overwritten.
A list of properties that can be mapped to Onspring fields can be found in the Microsoft Graph API documentation:
Note: Only properties that are of primitive types can be mapped to Onspring fields. Complex types are not supported.
Prior to the app actually attempting to sync groups or users it will validate the mappings that have been passed to it in the configuration file. Specifically it will check to make sure that all the required fields have a property mapped to them. It will also validate that the type of field a property is mapped to is compatible with the type of the property.
Onspring Group Field |
---|
Name |
Onspring User Field |
---|
Username |
First Name |
Last Name |
Email Address |
Groups |
Azure Property Type | Onspring Field Type |
---|---|
String |
Text |
String |
List |
String Collection |
Text |
String Collection |
Multi-Select List |
Boolean |
Text |
Boolean |
List |
DateTimeOffset |
Text |
DateTimeOffset |
Date/Time |
This app currently has a number of options that can be passed as command-line arguments to alter the behavior of the app. Theres are detailed below and can also be viewed by passing the -h
or --help
option to the app.
- Log Level:
--log
or-l
- Allows you to specify what the minimum level of event that will be written to the log file while the app is running.
- By default this will be set to the Verbose level.
- The valid levels are: Debug | Error | Fatal | Information | Verbose | Warning
- Example usage:
OnspringAzureADSyncer.exe -l warning
Each time the app runs it will generate a new folder that will be named based upon the time at which the app began running and the word output
in the following format: YYYY_MM_DD_HHMMSS_output
. All files generated by the app during the run will be saved into this folder.
Example Output Folder Name:
2023_03_12_205901_output
In addition to the information the app will log out to the console as it is running a log file will also be written to the output folder that contains information about the completed run. This log can be used to review the work done and troubleshoot any issues the app may have encountered during the run. Please note that each log event is written in Compact Log Event Format. You are welcome to parse the log file in the way that best suits your needs.
Various tools are available for working with the CLEF format.
- Analogy.LogViewer.Serilog - CLEF parser for Analogy Log Viewer
- clef-tool - a CLI application for processing CLEF files
- Compact Log Format Viewer - a cross-platform viewer for CLEF files
- Seq - import, search, analyze, and export application logs in the CLEF format
- seqcli - pretty-print CLEF files at the command-line
Example log message:
{"@t":"2023-03-13T01:56:45.2880591Z","@mt":"Starting syncer"}
{"@t":"2023-03-13T01:56:46.6855315Z","@mt":"Connected successfully to Onspring and Azure AD"}
{"@t":"2023-03-13T01:56:46.6860213Z","@mt":"Retrieving fields for Onspring Groups app"}
{"@t":"2023-03-13T01:56:47.0317460Z","@mt":"Retrieving fields for Onspring Users app"}
{"@t":"2023-03-13T01:56:47.2437652Z","@mt":"Setting default Groups field mappings"}
- The app will not support deleting groups or users in Onspring. It will only support creating and updating groups and users.
- The application will only support syncing groups and users in Azure Active Directory that are in the same tenant as specified in the configuration file.
- The application will only support syncing groups and users in Onspring that are in the same Onspring instance as that identified by the configured
ApiKey
. - The application will only support syncing groups and users between one Onspring instance and one Azure Active Directory tenant.
Note: You can run the app multiple times with different configuration values to allow for syncing groups and users for multiple tenants into multiple instances.
This project is licensed under the MIT License - see the LICENSE file for details
This project was built as a submission for the Microsoft Graph Hackathon 2023. The project was built using the Microsoft Graph .NET SDK and the Onspring API .NET SDK. It illustrates a solution to a real world challenge that Onspring customers face when trying to find a way to leverage their existing identity management solution in Azure AD to also manage groups and users in Onspring.