parent
fc896614c7
commit
7f0a14ee07
@ -1,11 +0,0 @@
|
||||
---
|
||||
slug: first-post
|
||||
title: First Post
|
||||
author: luffyZh
|
||||
author_title: 第一篇文章 @ Facebook
|
||||
author_url: https://github.com/luffyZh
|
||||
author_image_url: https://avatars.githubusercontent.com/u/17840558?s=60&v=4
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
## 第一篇文章
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
slug: hola
|
||||
title: Hola
|
||||
author: Gao Wei
|
||||
author_title: Docusaurus Core Team
|
||||
author_url: https://github.com/wgao19
|
||||
author_image_url: https://avatars1.githubusercontent.com/u/2055384?v=4
|
||||
tags: [hola, docusaurus]
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
@ -1,17 +0,0 @@
|
||||
---
|
||||
slug: hello-world
|
||||
title: Hello
|
||||
author: Endilie Yacop Sucipto
|
||||
author_title: Maintainer of Docusaurus
|
||||
author_url: https://github.com/endiliey
|
||||
author_image_url: https://avatars1.githubusercontent.com/u/17883920?s=460&v=4
|
||||
tags: [hello, docusaurus]
|
||||
---
|
||||
|
||||
Welcome to this blog. This blog is created with [**Docusaurus 2**](https://docusaurus.io/).
|
||||
|
||||
<!--truncate-->
|
||||
|
||||
This is a test post.
|
||||
|
||||
A whole bunch of other information.
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
slug: welcome
|
||||
title: Welcome
|
||||
author: Yangshun Tay
|
||||
author_title: Front End Engineer @ Facebook
|
||||
author_url: https://github.com/yangshun
|
||||
author_image_url: https://avatars0.githubusercontent.com/u/1315101?s=400&v=4
|
||||
tags: [facebook, hello, docusaurus]
|
||||
---
|
||||
|
||||
Blog features are powered by the blog plugin. Simply add files to the `blog` directory. It supports tags as well!
|
||||
|
||||
Delete the whole directory if you don't want the blog features. As simple as that!
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
slug: last-post
|
||||
title: Last Post
|
||||
author: luffyZh
|
||||
author_title: 最后一篇文章 @ Facebook
|
||||
author_url: https://github.com/yangshun
|
||||
author_image_url: https://avatars.githubusercontent.com/u/17840558?s=60&v=4
|
||||
tags: [test]
|
||||
---
|
||||
|
||||
## 我是最后一篇文章
|
@ -0,0 +1,87 @@
|
||||
---
|
||||
slug: understanding-scim-and-directory-sync
|
||||
title: Understanding SCIM and Directory Sync
|
||||
author: Kiran K
|
||||
author_title: Senior Developer @BoxyHQ
|
||||
author_url: https://twitter.com/tokirankrishnan
|
||||
author_image_url: https://boxyhq.com/img/team/kiran.jpg
|
||||
tags_disabled:
|
||||
[enterprise-readiness, engineering, saml-jackson, directory-sync, scim]
|
||||
image: /img/blog/directory-sync-flow.png
|
||||
---
|
||||
|
||||
This article will walk you through everything you should know about SCIM and Directory Sync.
|
||||
|
||||
## What is SCIM?
|
||||
|
||||
System for Cross-domain Identity Management (SCIM) is an open standard that allows for the automation of user provisioning (Directory Sync).
|
||||
|
||||
SCIM facilitates user identity data communication between Identity Providers (Okta, OneLogin, etc.) and Service Providers (Enterprise SaaS apps).
|
||||
|
||||
## Why should you care about SCIM?
|
||||
|
||||
Many companies manually onboard and offboard users, which consumes many IT resources and time.
|
||||
|
||||
User lifecycle management (ULM) begins when employees start their job and continue until they leave the company. ULM is all about provisioning and de-provisioning users when they join an organization.
|
||||
|
||||
For IT departments, this means creating an account for the new employees in the cloud apps they need to use after starting their job. Also, IT departments must ensure that when those employees leave, they revoke access to those accounts.
|
||||
|
||||
Smaller organizations might address these procedures manually, but the process can become error-prone and time-consuming when done at scale. This is where the SCIM and Directory Sync come to the organization's rescue.
|
||||
|
||||
## What is Directory Sync?
|
||||
|
||||
Directory sync helps organizations automate the provisioning and de-provisioning of their users.
|
||||
|
||||
As a result, it streamlines the user lifecycle management process by saving valuable organizational hours, creating a single truth source of the user identity data, and facilitating them to keep the data secure.
|
||||
|
||||
## How does the Directory Sync work?
|
||||
|
||||
Directory sync allows programmatic access to the user identity data via a standard protocol (SCIM).
|
||||
|
||||
Directory sync implementation typically involves a client and a server. A client is an identity provider (IDP) with a directory of user identities. A service provider (SP) is an enterprise SaaS app that needs a subset of data from those identities.
|
||||
|
||||
When you make changes to the user identities, the changes are automatically synced to the SP according to the SCIM protocol. SP can now process this data according to the way they want.
|
||||
|
||||
Some common user identity changes include adding new users to the organization, updating existing users, removing users from the organization, adding users to groups, etc.
|
||||
|
||||
Technically, SCIM is a set of APIs that allows you to manipulate the users and group objects and expose these data as JSON through the REST endpoints.
|
||||
|
||||
## How to add Directory Sync to your SaaS app?
|
||||
|
||||
Building Directory sync implementation yourself can be tedious and time-consuming for any engineering team.
|
||||
|
||||
Below are some questions the engineering team should answer before starting building Directory sync.
|
||||
|
||||
- How do we support multiple identity providers?
|
||||
- How much effort should the team put into support & maintenance?
|
||||
- Do we have developers with good knowledge of SCIM and its security?
|
||||
- Is it worth building the Directory sync ourselves?
|
||||
|
||||
In short, building Directory sync yourself is not a good idea. It requires a lot of tedious engineering work and ongoing maintenance.
|
||||
|
||||
The best alternative is an open-source dedicated Directory Sync implementation provider like SAML Jackson from BoxyHQ.
|
||||
|
||||
## Directory Sync from BoxyHQ
|
||||
|
||||
BoxyHQ can help enterprises to add Directory Sync to any SaaS app with just a few lines of code.
|
||||
|
||||
Enterprise SaaS apps can provide a Webhook endpoint to SAML Jackson, and Jackson will notify the Webhook every time a change occurs in the user identity data within the IDP.
|
||||
|
||||

|
||||
|
||||
In short, Jackson hides all the complexities involved with Directory Sync implementation and makes your integration easier.
|
||||
|
||||
BoxyHQ's Directory Sync implementation supports identity providers such as Okta, OneLogin, Azure AD, and JumpCloud. We're looking forward to adding more identity providers in future releases.
|
||||
|
||||
Here are a few critical aspects that make [BoxyHQ's Directory Sync implementation](/docs/directory-sync/overview) stand out.
|
||||
|
||||
- An open-source solution.
|
||||
- Allows you to keep control of your data.
|
||||
- Support multiple identity providers.
|
||||
- Allows you to listen to six critical SCIM events.
|
||||
|
||||
## Final Thoughts
|
||||
|
||||
Directory Sync is a valuable investment for every organization seeking efficiency and security in their user lifecycle management system.
|
||||
|
||||
If you are interested in becoming enterprise-ready without the hassle, then let's chat! You can book a free consultation call and talk with our CEO about how we can help. So let's start the journey together.
|
@ -0,0 +1,126 @@
|
||||
---
|
||||
slug: enterprise-ready-saas-starter-kit
|
||||
title: Enterprise-ready SaaS Starter Kit
|
||||
author: Kiran K
|
||||
author_title: Senior Developer @BoxyHQ
|
||||
author_url: https://twitter.com/tokirankrishnan
|
||||
author_image_url: https://boxyhq.com/img/team/kiran.jpg
|
||||
tags_disabled: [enterprise-readiness, nextjs-template, saas-starter-kit]
|
||||
---
|
||||
|
||||
Enterprise-ready SaaS Starter Kit is a **Next.js** based SaaS Starter Kit that can save hundreds of development hours while building [enterprise-ready SaaS apps](/blog/enterprise-readiness-made-simple).
|
||||
|
||||
[Kickstart your enterprise app development with Next.js SaaS Starter Kit](https://github.com/boxyhq/saas-starter-kit)
|
||||
|
||||
Check out the [video tutorial](https://youtu.be/oF8QIwQIhyo) that walks through setting up your local environment and running enterprise-ready features the SaaS kit offers.
|
||||
|
||||
## SAML SSO
|
||||
|
||||
SAML stands for Security Assertion Markup Language. It is an XML-based open standard for transferring identity data between an identity provider (IdP) and a service provider (SP).
|
||||
|
||||
[Single Sign On (SSO)](/blog/understanding-saml-sso-the-basics-from-the-solution-providers-side) allows your customers to manage their team's users outside your built-in user table.
|
||||
|
||||
SAML SSO is integrated with the help of [SAML Jackson](https://github.com/boxyhq/jackson)
|
||||
|
||||
## Directory Sync (SCIM)
|
||||
|
||||
[Directory sync](/blog/understanding-scim-and-directory-sync) helps organizations automate the provisioning and de-provisioning of their users.
|
||||
|
||||
As a result, it streamlines the user lifecycle management process by saving valuable organizational hours, creating a single truth source of the user identity data, and facilitating them to keep the data secure.
|
||||
|
||||
Directory Sync is integrated with the help of [SAML Jackson](https://github.com/boxyhq/jackson#directory-sync)
|
||||
|
||||
## Audit Logs
|
||||
|
||||
Provide enterprise customers with the ability to record and search events that happen within your application. With our simple integration, you can become compliant fast and save your team from building complex solutions from scratch.
|
||||
|
||||
Organizations gain the ability to monitor the flow of data and be alerted to any breaches. Audit logs help to pinpoint any misuse of information and ensure that data policies are followed.
|
||||
|
||||
## Webhooks & Events
|
||||
|
||||
Webhooks are a way for systems to notify external applications that a specific event has occurred in your SaaS app without receiving a request.
|
||||
|
||||
Webhooks are a great solution if the client does not know when an event will occur and wants to be notified in real-time.
|
||||
|
||||
Webhook is integrated with the help of [Svix](https://github.com/svix/svix-webhooks)
|
||||
|
||||
## Team Management
|
||||
|
||||
Teams describe the functionality that enables modern software to be coordinated and managed.
|
||||
|
||||
Through Teams, SaaS app users invite others to collaboratively use the application with them by creating an account.
|
||||
|
||||
## Other Features
|
||||
|
||||
Let's also look at other standard features the SaaS kit offers.
|
||||
|
||||
- Create account
|
||||
- Sign in with Email and Password
|
||||
- Sign in with Magic Link
|
||||
- Update account
|
||||
- Manage team
|
||||
- Manage team members
|
||||
- Invite users to the team
|
||||
- Accept invitation
|
||||
|
||||
## Getting Started
|
||||
|
||||
Please follow these simple steps to get a local copy up and running.
|
||||
|
||||
### 1. Setup
|
||||
|
||||
Clone or fork this GitHub repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/boxyhq/saas-starter-kit.git
|
||||
```
|
||||
|
||||
### 2. Go to the project folder
|
||||
|
||||
```bash
|
||||
cd saas-starter-kit
|
||||
```
|
||||
|
||||
### 3. Install dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### 4. Set up your .env file
|
||||
|
||||
Duplicate `.env.example` to `.env`.
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
### 5. Set up database schema
|
||||
|
||||
```bash
|
||||
npx prisma db push
|
||||
```
|
||||
|
||||
### 6. Start the server
|
||||
|
||||
In a development environment:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 7. Start the Prisma Studio
|
||||
|
||||
Prisma Studio is a visual editor for the data in your database.
|
||||
|
||||
```bash
|
||||
npx prisma studio
|
||||
```
|
||||
|
||||
## Contributing guide
|
||||
|
||||
Contributions make the open-source community a fantastic place to learn, inspire, and create. Any contributions are greatly appreciated by the whole community.
|
||||
|
||||
We encourage and invite users and community members to contribute to the [saas-starter-kit](https://github.com/boxyhq/saas-starter-kit) repository.
|
||||
|
||||
For more help or if you have a question about getting started building a SaaS app please join our [Community Discord.](https://discord.boxyhq.com)
|
@ -0,0 +1,83 @@
|
||||
---
|
||||
slug: sso-building-blocks
|
||||
title: SSO Building blocks - SAML, OAuth 2.0 and OpenID Connect
|
||||
author: Aswin V
|
||||
author_title: Senior Developer @BoxyHQ
|
||||
author_url: https://twitter.com/av__2021
|
||||
author_image_url: https://boxyhq.com/img/team/aswin.jpg
|
||||
tags_disabled: [sso, engineering, saml-jackson, oauth-2.0]
|
||||
image: /img/sso-flow.png
|
||||
---
|
||||
|
||||
We have already covered SAML at a high level from both [user](2022-06-30-understanding-saml-sso-the-basics-from-the-user-side.md) and [application provider](2022-06-30-understanding-saml-sso-the-basics-from-the-solution-providers-side.md) points of view.
|
||||
|
||||
In this post, we'll dive into the technicalities of SAML, OAuth 2.0 and OpenID Connect and how these come together to serve as building blocks for Jackson SSO.
|
||||
|
||||
## SAML
|
||||
|
||||
SAML was designed for traditional web applications in the early 2000s. The goal was to provide a seamless user experience for applications by federating authentication to an IdP. As a result, applications no longer had to maintain identities for users. All they had to do was to redirect the browser to the IdP which would then authenticate the user and return an assertion about the logged-in user. This assertion in effect was a token, asserting to the app that the user authenticated at the IdP and the assertion is valid for the set period contained within it.
|
||||
|
||||
While SAML gave us a solution to the problem of SSO or federated identity, it does not address the issue of authorization.
|
||||
|
||||
The need for authorization arose with the dawn of Single Page Apps (SPA) and native platforms such as mobile. More and more logic started moving from backend to frontend and an ecosystem of apps that could talk to one another (via HTTP(S)) sprung up. For eg:- You could reserve movie tickets and send invitations to your Facebook friends. This meant that applications started acting on behalf of the end-user, requesting data (friend list) from other services (Facebook). One way we could solve it was by sharing our credentials (for services) with the app. Nothing could be more dangerous than this, because now the application can virtually do anything the user could do. This paved the path for standards like OAuth that provides us with a mechanism to grant controlled and limited access to resources on behalf of the user.
|
||||
|
||||
## OAuth 2.0
|
||||
|
||||
The OAuth 2.0 Authorization framework enables a third-party application/client to obtain limited access to an HTTP service on behalf of the resource owner (or user). In the final step of this process, the client receives a short-lived access token that can be used to access the protected resources.
|
||||
|
||||
The flow starts with the app redirecting the user agent to an intermediary Authorization server (AS). The AS authenticates the user and obtains permission from the user to access resources. Once that's done, AS redirects back to the client with an Authorization code. The Authorization code is a grant or a credential representing the user's authorization to be used by the client. In the final step, the client uses this code to obtain an access token. This flow otherwise called Authorization Code grant is one of 4 grant types that are supported. For sake of simplicity, we can omit the others for now.
|
||||
|
||||
The above-mentioned flow offers a few benefits:
|
||||
|
||||
- The user only authenticates with the authorization server and the credentials are never shared with the app.
|
||||
- The access token is not transmitted<sup>\*</sup> via the user agent but directly to the client via an HTTP request.
|
||||
- The Client can be authenticated by the authorization server by using a client secret.
|
||||
|
||||
**\*** _It's worth mentioning the fact that another grant type 'implicit grant' does return an access token via the user agent in the redirect URL fragment_
|
||||
|
||||
#### Using OAuth 2.0 for authentication
|
||||
|
||||
Since authentication usually occurs before issuing the access token, it is usually assumed that possession of an access token is proof that authentication happened. The access token is then used to query the Identity API to obtain user details.
|
||||
|
||||
However, this does not fully serve as proof of authentication and has several pitfalls:
|
||||
|
||||
- The access token is opaque to the client and its intended audience is the protected resource server.
|
||||
- There is no way to know if the user is still around because information about the authentication event is not exposed.
|
||||
- In situations where clients get an access token directly in the return URL (implicit grant), there is a high chance that an attacker can inject their malicious token. This can be mitigated by using the Authorization code flow as the token is retrieved from the token endpoint directly.
|
||||
- OAuth does not define a standard set of fields for the Identity API. For eg:- While one IdP could use `user_id` for the user identifier, the same could be `subject` in another one. This requires different handling on the client side from one IdP to another.
|
||||
|
||||
A new standard called 'OpenID Connect' which builds on top of OAuth 2.0 brings new artifacts like ID tokens that can serve as reliable proof of authentication and also standardizes things like `scope` and `claims`.
|
||||
|
||||
## OpenID Connect (OIDC)
|
||||
|
||||
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It supports 3 flows of which Authorization code and implicit flow are similar to the ones defined in OAuth 2.0. The notable difference here is the return of an ID Token in JWT format (JSON Web Token). The claims in the ID Token help the client reliably confirm the identity of the user. The audience(`aud`) claim will be set to the client id which means the ID token is intended to be consumed by the client alone. Conforming to the OAuth 2.0 spec, an access token is still returned which can be used to obtain information about the user from the "userinfo" endpoint. OIDC also standardizes the claims in the ID Token as well as the "userinfo" response.
|
||||
|
||||
## Assembling the SSO puzzle
|
||||
|
||||
Now that we have all the pieces of the SSO puzzle, bringing it together in Jackson would look something like the one below.
|
||||
|
||||

|
||||
|
||||
Allow me to explain.
|
||||
|
||||
We need to support two kinds of SSO Identity Providers - SAML and OIDC. For the sake of discussion, consider the scenario of two apps where one (CRM) needs to log in with Azure AD via SAML and another (HRM) needs to log in with Google Workspace via OIDC.
|
||||
|
||||
#### Setup SSO Connection
|
||||
|
||||
The preliminary step (marked by the green arrow above) is to add the SSO Connection to Jackson. For SAML IdP, this would mean saving the XML metadata from the IdP. The metadata would contain the SSO URL to send the SAML request to plus the public key to verify the SAML assertion signature. In the case of OIDC IdP, we need the discovery URL and client credentials (clientID and clientSecret of the registered app). The discovery URL can be used to query metadata about IdP such as authorization and token endpoints while the client credentials will be used to authenticate the Jackson client orchestrating the OIDC flow.
|
||||
|
||||
#### Login flow
|
||||
|
||||
Jackson supports both OAuth 2.0 and OpenID flows. The OAuth 2.0 flow is made secure by supporting Authorization Code flow with PKCE. By including the scope `openid` in the client request Jackson will switch to OpenID flow.
|
||||
|
||||
The login process follows the below steps:
|
||||
|
||||
1. The Client (Browser app) initiates the login by redirecting to Jackson's `authorize` endpoint. Jackson will parse the tenant/product in the request and use it to redirect the user to the configured IdP.
|
||||
2. Step 2 varies based on the Identity Provider type. For SAML IdP, Jackson would construct the SAML request, sign it and send it to IdP. The IdP validates the request and authenticates the user. For OIDC IdP, Jackson constructs an OpenID Connect request and redirects the user to the OIDC Provider authorization endpoint.
|
||||
3. Once the user is logged in successfully, the IdP redirects back to Jackson. For SAML, the response contains the user profile. In the case of OIDC, the response contains the authorization code that is used by Jackson to obtain the token and user profile from the OIDC IdP. Jackson generates a short-lived `authorization code` and stores the user profile against it.
|
||||
4. The `authorization code` generated in the previous step is sent to the client app.
|
||||
5. The client exchanges the code for the token and uses it to query the userInfo endpoint of Jackson to get the complete user profile. In the case of OpenID flow, ID Token is returned by Jackson and contains the basic user profile.
|
||||
|
||||
## Final thoughts
|
||||
|
||||
So in a nutshell, Jackson acts as a proxy between the client app and the IdP doing the heavy lifting of orchestrating SAML/OIDC flows with the configured IdPs. This way you can quickly scale your app auth to any number of providers allowing you to focus on your core product.
|
@ -0,0 +1,46 @@
|
||||
---
|
||||
slug: what-is-dev-ops-and-how-has-it-evolved-into-dev-sec-ops
|
||||
title: What is DevOps and how has it evolved into DevSecOps
|
||||
author: Jay Singh
|
||||
author_title: Marketing Consultant
|
||||
author_url: https://www.linkedin.com/in/jaydsingh/
|
||||
author_image_url: https://boxyhq.com/img/team/jay.jpg
|
||||
tags_disabled: [devops, devsecops, developer security]
|
||||
image: /img/blog/devsecops.png
|
||||
---
|
||||
|
||||
## What is DevOps
|
||||
|
||||
Let's first take a look at what DevOps (Developer Operations) is so we can better understand why it has now evolved into DevSecOps (Developer Security Operations). DevOps is a combination of philosophies, practices, and tools that increases a business's ability to deliver better development in less time (Higher velocity). This can be applied to building a new product or the process of continuous improvement that applies to most products we see today.
|
||||
|
||||
If we look at the old way of development, typical teams worked on their own and would do their bit and then just pass it on to the next team to do theirs, a bit like an assembly line. This meant that development cycles were very long, communication between teams was limited, handover processes were not in place and if anything went wrong it would take a long time to identify and fix issues. If we compare that to today's agile development process we use DevOps to work in sprints and deliver results in a much faster and more efficient way. This has been made possible by not only the way we look at the development cycle but also by tools and automation.
|
||||
|
||||
DevOps has come a long way already and we have seen it evolve with the agile methodology of working but security, in particular, was always still the last step of the development process and not thought about as a necessity. In some cases when security was only looked at by a specific team at the end of the process.
|
||||
|
||||
## Why has security been integrated into DevOps
|
||||
|
||||
The rise in cybercrime and the sophistication of attacks has made security a crucial part of the development process and not just an afterthought. This has led to security being integrated into the development process at each stage and becoming a shared responsibility. It has also led to security being thought about and planned right from the start of each process rather than at the end. This has resulted in more development velocity, more layers of integrated security and higher collaboration around security as a major aspect of the development cycle.
|
||||
|
||||
The integration of security in the development cycle at each stage from start to finish while also automating some of the security steps is what has led to the evolution of DevOps becoming DevSecOps, a go-to practice today. One of the main reasons the term was adjusted to include security is to make each person in the process think about and take accountability for secure building practices.
|
||||
|
||||
## Benefits of DevSecOps
|
||||
|
||||
Lastly, let's take a quick look at the main benefits of having solid DevSecOps in place
|
||||
|
||||
1. **Security**
|
||||
|
||||
By thinking about and implementing security at each stage of the development process and particularly in the early stages organizations are proactively mitigating cyber threats. This combined with automated security testing means that dev teams can perform security checks and audits without slowing down development cycles.
|
||||
|
||||
2. **Improved Collaboration**
|
||||
|
||||
DevSecOps pushes for development and security and operations teams to collaborate more and especially in the early stages of the process. This increases innovation and leads to better cross-team buy-in. It also makes sure that everyone is responsible for security.
|
||||
|
||||
3. **Streamlines process that limits vulnerabilities**
|
||||
|
||||
Having security in every stage of the development process limits the chance of finding vulnerabilities much later, vulnerabilities which could delay the release. The process of streamlining the process with automated security testing as part of the development process also ensures that possible vulnerabilities are caught at each stage.
|
||||
|
||||
4. **Cost**
|
||||
|
||||
Cost is also always a major benefit and by having a good DevSecOps process in place you will find bugs and issues much faster which will result in less time and cost required to fix them.
|
||||
|
||||

|
@ -0,0 +1,34 @@
|
||||
---
|
||||
slug: ignite-your-saas-journey-with-the-best-free-and-open-source-saas-starter-kit
|
||||
title: 'Ignite Your SaaS Journey with the Best Free and Open-Source SaaS Starter Kit'
|
||||
author: Sama - Carlos Samame
|
||||
author_title: Co-founder & COO @BoxyHQ
|
||||
author_url: https://www.linkedin.com/in/samame/
|
||||
author_image_url: https://boxyhq.com/img/team/sama.jpg
|
||||
tags_disabled: [developer, security, saas, devsecops, appsec]
|
||||
image: /img/blog/enterprise-ready-saas.jpg
|
||||
---
|
||||
|
||||

|
||||
|
||||
Discover the Game-Changing Power of an Enterprise-Ready Solution that will help you save thousands of dollars in development costs.
|
||||
|
||||
Are you a SaaS founder striving for accelerated success in the highly competitive landscape? Look no further! At BoxyHQ we've curated a revolutionary tool that will supercharge your SaaS journey like never before. Introducing the Best Free and Open-Source SaaS Starter Kit, designed to ignite your growth and transform your startup dreams into reality.
|
||||
|
||||
## Enterprise-Ready Powerhouse
|
||||
|
||||
We understand that conquering the enterprise market is a key milestone for many SaaS founders. That's why this Starter Kit is not just another ordinary tool—it's an enterprise-ready powerhouse. Equipped with robust security features and compliance readiness, it's tailored to meet the stringent requirements of corporate clients. It includes SAML/OIDC Single Sign-On (SSO), Directory Sync, Audit Logs, and Data Privacy Vault (PII, PCI, PHI compliant) that would cost tens of thousands of dollars in developer time. Empower your startup to take on the biggest players in the industry with confidence.
|
||||
|
||||
## Supercharge Your Development Journey
|
||||
|
||||
Leave the tedious and time-consuming development tasks behind. The SaaS Starter Kit empowers founders to supercharge their development journey. Its intuitive, no-code capabilities streamline the entire process, enabling you to focus on your unique value proposition. Join the ranks of successful SaaS startups who have harnessed the power of this kit to achieve rapid growth and customer acquisition.
|
||||
|
||||
## Get Started Today
|
||||
|
||||
Ready to unlock your SaaS potential? Getting started is a breeze. Simply access the Starter Kit's source code and documentation on GitHub, available at [here](https://github.com/boxyhq/saas-starter-kit)
|
||||
|
||||
For additional guidance and insider tips, head over to this other [blog post](https://boxyhq.com/blog/enterprise-ready-saas-starter-kit) and watch our [full demo](https://www.youtube.com/watch?v=oF8QIwQIhyo). It's time to embark on your journey toward SaaS greatness.
|
||||
|
||||
Don't let your SaaS dreams remain stagnant—ignite them with the best free and OSS enterprise-grade SaaS Starter Kit. This game-changing tool is set to revolutionize the way startups grow and succeed. Seize the opportunity, join our thriving community, and accelerate your path to SaaS stardom. The possibilities are limitless, and your success awaits!
|
||||
|
||||

|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"label": "Bot市场",
|
||||
"position": 8
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"label": "DevOps引擎(Engine)",
|
||||
"position": 6
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
---
|
||||
sidebar_label: '代码流水线'
|
||||
sidebar_position: 5
|
||||
---
|
||||
# 代码流水线
|
||||
可以通过代码的形式(YAML格式)来配置流水线,首先选择代码流水线和对应的分支:
|
||||
|
||||

|
||||
|
||||
编辑流水线代码,其流水线名称描述、触发器、全局参数、执行串行/并发和流水线编排等概念同图形流水线,具体描述如下:
|
||||
|
||||

|
@ -1,15 +0,0 @@
|
||||
---
|
||||
sidebar_label: '参数配置'
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# 参数配置
|
||||
|
||||
可在流水线中使用,实现动态参数配置;有字符串、数字、布尔三种类型。
|
||||
|
||||

|
||||
|
||||
|
||||
在流水线的配置中通过如下方式获取参数:
|
||||
|
||||

|
@ -1,16 +0,0 @@
|
||||
---
|
||||
sidebar_label: '密钥设置'
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# 密钥设置
|
||||
|
||||
将账号密码、密钥、证书等存放到密钥管理里,配置后可直接在流水线中使用,避免因直接填写引起的泄露风险。
|
||||
|
||||

|
||||
|
||||
使用示例
|
||||
|
||||
注:节点输入参数中,下拉选项为密钥类型,需要提前配置好密钥在流水线中选择使用
|
||||
|
||||

|
@ -1,10 +0,0 @@
|
||||
---
|
||||
sidebar_label: '执行记录查询'
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# 执行记录查询
|
||||
|
||||
用户可以查看流水线的运行状态
|
||||
|
||||

|
@ -0,0 +1,91 @@
|
||||
---
|
||||
title: Manage Audit logs Admin Portal
|
||||
sidebar_label: Audit Logs
|
||||
---
|
||||
|
||||
# Admin Portal
|
||||
|
||||
Retraced can be accessed using Admin interface that allows you to manage Projects & Environments via UI. To enable the Admin Portal, make sure you deploy [Retraced with Docker Compose](../retraced/self-host/docker.md)
|
||||
|
||||
You can open the Admin Portal on port `5225`.
|
||||
|
||||
## Sign into Admin Portal
|
||||
|
||||
We use [Magic Links](https://next-auth.js.org/providers/email) to authenticate users to the UI.
|
||||
|
||||
You'll need to set the following configuration in the [environment](../jackson/deploy/env-variables.md#admin-ui-configuration):
|
||||
|
||||
1. SMTP Server details, so we can send you the email with the magic link.
|
||||
2. Access Control List which is an array of emails or glob patterns. Only these users will be allowed access to the Admin Portal. Example: `tonystark@gmail.com,*@marvel.com`.
|
||||
|
||||
Follow the below steps to login into the Admin dashboard.
|
||||
|
||||
- Visit the path `/api/auth/signin` on your app. The page will display a sign-in page with a text box to enter the email address.
|
||||
- Enter the email address that matches the `NEXTAUTH_ACL` and click the button **Sign in with Email**.
|
||||
- Open the inbox and you'll see an email from Jackson.
|
||||
- Open that email and click the button **Sign in**. Now you've successfully logged into the BoxyHQ Admin Portal.
|
||||
- Click on the Audit Logs menu from the sidebar on the left to access the Retraced service.
|
||||
|
||||
## Fresh Start
|
||||
|
||||
When you are setting up the Audit logs for the first time with Retraced, you won't have any **Projects** in the system or in case you run bootstrap script as a part of your deployment you will have **dev** project.
|
||||
|
||||

|
||||
|
||||
## Create Project
|
||||
|
||||
Just click on **Create Project** or **Add Project** button to initiate new Project creation.
|
||||
You just need to enter the name of the project and click on **Create Project** button.
|
||||
|
||||

|
||||
|
||||
## Project Information
|
||||
|
||||
You will get see the **Project Information** after the Project is created.
|
||||
This page shows,
|
||||
|
||||
1. Project ID
|
||||
2. Production Token
|
||||
3. Staging Token
|
||||
4. Publisher API Base URL
|
||||
5. POST request URL to ingest your events
|
||||
6. Example CURL command to send test events
|
||||
|
||||

|
||||
|
||||
## Send test event with CURL
|
||||
|
||||
You can copy and paste the curl command in terminal or command prompt.
|
||||
After execution of command you should see **id & hash** as output.
|
||||
|
||||

|
||||
|
||||
## Project List
|
||||
|
||||
Now if you click on Audit Logs you should see newly created Project there.
|
||||
|
||||
You can perform following actions:
|
||||
|
||||
- You can click on first button under actions the **tools** button to open the **Project Information** page.
|
||||
- You can click on second button under actions, the button with **magnifying glass** to see the **logs**.
|
||||
|
||||

|
||||
|
||||
## Select Environment & Group
|
||||
|
||||
When you create a Project by default following environments are created
|
||||
|
||||
- Production
|
||||
- Staging
|
||||
|
||||
Every Environment can have multiple Tenants.
|
||||
|
||||

|
||||
|
||||
## View Logs
|
||||
|
||||
Once you select the Environment you will see the Tenants listed in the dropdown.
|
||||
For this example you will see **BoxyHQ** listed in the dropdown for **Staging Environment**.
|
||||
Once you select the **Tenant** you will the logs listed down on the page.
|
||||
|
||||

|
@ -0,0 +1,81 @@
|
||||
---
|
||||
title: Manage Directory Sync using Admin Portal
|
||||
sidebar_label: Directory Sync
|
||||
---
|
||||
|
||||
# Manage Directories
|
||||
|
||||
On the Admin Portal **Directory Sync** menu, you can see the Directory connections.
|
||||
|
||||
## Create Directory Sync connection
|
||||
|
||||
1. From your Admin Portal, go to **Directory Sync**.
|
||||
2. Click **Create New**.
|
||||
3. Enter the following information:
|
||||
- Enter **Directory name**
|
||||
- Select the **Directory provider** from the list of [available providers](../directory-sync/providers/).
|
||||
- Add the **Tenant**
|
||||
- Add the **Product**
|
||||
- Enter the **Webhook URL**
|
||||
- Enter the **Webhook secret**
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Update Directory Sync connection
|
||||
|
||||
1. From your Admin Portal, go to **Directory Sync**.
|
||||
2. From the list of directory sync connections, click edit icon.
|
||||
3. You can update the following information:
|
||||
- Enter **Directory name**
|
||||
- Enter the **Webhook URL**
|
||||
- Enter the **Webhook secret**
|
||||
- Toggle **Enable Webhook events logging**
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## View directory users
|
||||
|
||||
1. From your Admin Portal, go to **Directory Sync**.
|
||||
2. From the list of directory sync connections, click database icon.
|
||||
3. Click the tab **Users**.
|
||||
4. Click the eye icon to view the user raw JSON data.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## View directory groups
|
||||
|
||||
1. From your Admin Portal, go to **Directory Sync**.
|
||||
2. From the list of directory sync connections, click database icon.
|
||||
3. Click the tab **Groups**.
|
||||
4. Click the eye icon to view the group raw JSON data.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## View webhook events
|
||||
|
||||
1. From your Admin Portal, go to **Directory Sync**.
|
||||
2. From the list of directory sync connections, click database icon.
|
||||
3. Click the tab **Webhook Events**.
|
||||
4. Click the eye icon to view the event raw JSON data.
|
||||
|
||||

|
||||
|
||||
Click the button **Clear Events** to delete all events from the database.
|
||||
|
||||
---
|
||||
|
||||
## Enable webhook events logging
|
||||
|
||||
1. From your Admin Portal, go to **Directory Sync**.
|
||||
2. From the list of directory sync connections, click edit icon.
|
||||
3. You can enable or disable the **Enable Webhook events logging**.
|
||||
|
||||
By default, the webhook events are not logged.
|
@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Manage Enterprise SSO using Admin Portal
|
||||
sidebar_label: Enterprise SSO
|
||||
---
|
||||
|
||||
# Manage SSO Connections
|
||||
|
||||
On the Admin Portal **Enterprise SSO** menu, you can see the SSO Connections details.
|
||||
|
||||
## Add SAML Connections
|
||||
|
||||
Once you've set up the SAML app on your Identity Provider, the Identity Provider will generate a SAML Metadata file.
|
||||
|
||||
The SAML metadata file contains information about the various SAML Authorities that can be used in SAML 2.0 protocol message exchanges.
|
||||
|
||||
Download the SAML Metadata file from your IdP and follow the below steps for adding the SAML connection.
|
||||
|
||||
- Click the button **New Connection**.
|
||||
- Choose **SAML** as the type.
|
||||
- Give your new connection a **name**.
|
||||
- Add your **Tenant** (Eg: boxyhq.com) and **Product** (Eg: flex).
|
||||
- Add **Allowed redirect URLs**.
|
||||
- Add **Default redirect URL**.
|
||||
- Paste the **Raw IdP XML**.
|
||||
- If **ForceAuthn** is checked, it means that the user will be forced to re-authenticate at SAML IdP, even if they have an active session.
|
||||
- Click the button **Save Changes**.
|
||||
|
||||
Now you've successfully added your first SAML connection.
|
||||
|
||||
## Add OIDC Connections
|
||||
|
||||
Once you've registered the OIDC app on your Identity Provider, the Identity Provider will generate a clientId and clientSecret.
|
||||
|
||||
The `clientSecret` will be used to authenticate the oidc client (in this case jackson) and obtain the `access_token`.
|
||||
|
||||
Also get the OpenID provider [discovery](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig) endpoint (usually ending in `/.well-known/openid-configuration`) and follow the below steps for adding the OIDC connection.
|
||||
|
||||
- Click the button **New Connection**.
|
||||
- Choose **OIDC** as the type.
|
||||
- Give your new connection a **name**.
|
||||
- Add your **Tenant** (Eg: boxyhq.com) and **Product** (Eg: flex).
|
||||
- Add **Allowed redirect URLs**.
|
||||
- Add **Default redirect URL**.
|
||||
- Enter the URL for OpenID Provider discovery which exposes the Provider Metadata.
|
||||
- Paste the **clientId** and **clientSecret** values into Client ID [OIDC Provider]/Client Secret [OIDC Provider] fields in the UI.
|
||||
- Click the button **Save Changes**.
|
||||
|
||||
Now you've successfully added your first OIDC connection.
|
||||
|
||||
## SAML Federation
|
||||
|
||||
SAML Federation is an enterprise feature and you need to have an enterprise license to use this feature.
|
||||
|
||||
From the **Admin Portal** go to **Enterprise SSO** > **SAML Federation**.
|
||||
|
||||
### Create SAML Federation App
|
||||
|
||||
- Click **New App**.
|
||||
- Enter the following information:
|
||||
- **Name**
|
||||
- **Tenant**
|
||||
- **Product**
|
||||
- **ACS URL** (ACS URL of the SP)
|
||||
- **Entity ID** (Entity ID of the SP)
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### Update SAML Federation App
|
||||
|
||||
- From the list of SAML Federation Apps, click on the **Edit** icon of the app you want to update.
|
||||
- You can update the following information:
|
||||
- **Name**
|
||||
- **ACS URL** (ACS URL of the SP)
|
||||
- **Entity ID** (Entity ID of the SP)
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### View IdP Configuration
|
||||
|
||||
Click **View IdP Configuration** button to view the IdP configuration for the SAML Federation App. You need to provide the SP with the following information:
|
||||
|
||||
- **SSO URL**
|
||||
- **Entity ID / Audience URI / Audience Restriction**
|
||||
- **X.509 Certificate**
|
||||
|
||||

|
@ -0,0 +1,77 @@
|
||||
---
|
||||
title: Get Started with Admin Portal
|
||||
sidebar_label: Get Started
|
||||
---
|
||||
|
||||
# Get Started with Admin Portal
|
||||
|
||||
SAML Jackson comes with an Admin Portal that allows you to manage **Enterprise SSO**, **Directory Sync**, **Setup Links**, and **Audit Logs** products via an easy to use web interface.
|
||||
|
||||
Our future products (where relevant) will also be available in the Admin Portal.
|
||||
|
||||
To enable the Admin Portal, make sure you deploy [Jackson as a service](../jackson/deploy/service).
|
||||
|
||||
## Authentication Methods
|
||||
|
||||
BoxyHQ SAML Jackson supports multiple authentication methods. You can choose to use any of the following methods to authenticate users to the Admin Portal.
|
||||
|
||||
We use [NextAuth](https://next-auth.js.org) to handle authentication. Set the following environment variables to configure the authentication.
|
||||
|
||||
- `NEXTAUTH_URL`: The URL of your app.
|
||||
- `NEXTAUTH_SECRET`: A secret used to encrypt the session cookie. You can generate one using `openssl rand -base64 32`
|
||||
|
||||
### 1. Magic Links
|
||||
|
||||
With Magic Links, you can sign in to the Admin Portal without having to enter a password. The app will send you an email with a link to sign in. You'll need **SMTP server credentials** to send emails.
|
||||
|
||||
Configure the following environment variables to enable Magic Links.
|
||||
|
||||
- `SMTP_HOST`: SMTP server host
|
||||
- `SMTP_PORT`: SMTP server port
|
||||
- `SMTP_USER`: SMTP server username
|
||||
- `SMTP_PASSWORD`: SMTP server password
|
||||
- `SMTP_FROM`: From email address to use when sending Magic Link emails
|
||||
- `NEXTAUTH_ACL`: An array of emails or glob patterns. Only these users will be allowed access to the Admin Portal. For example: `NEXTAUTH_ACL=tonystark@gmail.com,*@marvel.com`
|
||||
|
||||
Follow the below steps to login into the Admin Portal.
|
||||
|
||||
- Visit the path `/api/auth/signin` on your app.
|
||||
- Enter the email address that matches the `NEXTAUTH_ACL` and click the button **Send Magic Link**.
|
||||
- Open the inbox and you'll see an email from SAML Jackson.
|
||||
- Open that email and click the button **Sign in**.
|
||||
|
||||
### 2. Email and Password
|
||||
|
||||
With Email and Password, you can sign in to the Admin Portal using an email address and password. You can use it as an alternative to Magic Links or SAML Single Sign-On. This is the easiest way to get started with the Admin Portal.
|
||||
|
||||
Configure the environment variable to enable Email and Password authentication.
|
||||
|
||||
- `NEXTAUTH_ADMIN_CREDENTIALS`: A comma separated list of email and password pairs. For example: `david@acme.com:secretpassword,john@acme.com:anotherpassword`
|
||||
|
||||
At the moment, set the password as plain text. We'll add support for encrypted passwords soon.
|
||||
|
||||
Follow the below steps to login into the Admin Portal.
|
||||
|
||||
- Visit the path `/api/auth/signin` on your app.
|
||||
- Enter the email address and password that matches the `NEXTAUTH_ADMIN_CREDENTIALS` and click the button **Sign In**.
|
||||
|
||||
### 3. SAML/OIDC Single Sign-On
|
||||
|
||||
With SAML/OIDC Single Sign-On, you can sign in to the Admin Portal using your Identity Provider. The app will redirect you to your Identity Provider to sign in. Once you've signed in, you'll be redirected back to the Admin Portal.
|
||||
|
||||
Configure the following environment variables to enable SAML/OIDC Single Sign-On.
|
||||
|
||||
- `ADMIN_PORTAL_SSO_TENANT`: This will be used as the tenant for the SSO connections. Set this to a value that is less likely to conflict with the main Enterprise SSO connections.
|
||||
- `ADMIN_PORTAL_SSO_PRODUCT`: This will be used as the product for the SSO connections. Set this to a value that is less likely to conflict with the main Enterprise SSO connections.
|
||||
|
||||
If not set, the default values will be used which are `_jackson_boxyhq` and `_jackson_admin_portal`.
|
||||
|
||||
To enable SAML/OIDC Single Sign-On, you'll need to access the Admin Portal using either [Magic Links](#1-magic-links) or [Email and Password](#2-email-and-password). Once you've logged in, you can configure SAML/OIDC Single Sign-On from the Admin Portal.
|
||||
|
||||
Go to **Settings** > **SSO for Admin Portal** and add a new SSO connection. We support both SAML and OIDC protocols.
|
||||
|
||||
Follow the below steps to login into the Admin Portal.
|
||||
|
||||
- Visit the path `/api/auth/signin` on your app.
|
||||
- Click the button **Login with SSO**.
|
||||
- You'll be redirected to your SAML Identity Provider to sign in for the authentication and then redirected back to the Admin Portal.
|
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: Setup Link (Directory-Sync)
|
||||
sidebar_label: Directory Sync
|
||||
description: Setup Link to create a Directory Sync
|
||||
---
|
||||
|
||||
# Setup Link (Directory Sync)
|
||||
|
||||
The Setup link is used to create a shareable link that can be used to create an Directory Sync without exposing any sensitive information.
|
||||
Let's go through the steps to create a new Setup link
|
||||
|
||||
## Create Setup Link
|
||||
|
||||
You can create a new Setup link for Directory Sync from the Connections page using `New Setup Link` button
|
||||
|
||||

|
||||
|
||||
Another way is to go to the `Setup Links` section under `Directory Sync` menu and Click on Create New/New Setup Link button
|
||||
|
||||

|
||||
|
||||
The create Setup Link for Directory Sync page looks like below
|
||||
|
||||

|
||||
|
||||
Once the link is created you can see the the link info section at the bottom
|
||||
|
||||

|
||||
|
||||
You can copy the link by clicking on the `Copy` button
|
||||
|
||||

|
||||
|
||||
### Regenerate Link
|
||||
|
||||
You can regenerate the link by clicking on `Regenerate` button
|
||||
|
||||

|
||||
|
||||
Once you confirm Regenerate action you will see the new setup link in the link info section
|
||||
|
||||

|
||||
|
||||
### Actions from Setup Link list page
|
||||
|
||||
You can perform `ACTIONS` like `Copy`, `View`, `Regenerate` & `Delete` from this page
|
||||
|
||||

|
||||
|
||||
### Setup Link Page
|
||||
|
||||
When you open the setup link you will see the following
|
||||
|
||||

|
||||
|
||||
### Create Directory Sync Connection
|
||||
|
||||
You can open create Directory Sync by clicking on `New Directory` button & filling the correct details
|
||||
|
||||

|
||||
|
||||
After creation of the directory sync you will see the info section
|
||||
|
||||

|
@ -0,0 +1,9 @@
|
||||
# Setup Link
|
||||
|
||||
Admin portal can be used to create setup links for
|
||||
|
||||
- [Enterprise SSO](./jackson)
|
||||
- [Directory-Sync](./directory-sync)
|
||||
|
||||
Setup links can be shared with anyone to let them set up connections for the products.
|
||||
These links come in handy for admins to facilitate setup by non-admin users without revealing any sensitive information or giving admin access unnecessarily.
|
@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Setup Link (Enterprise SSO)
|
||||
sidebar_label: Enterprise SSO
|
||||
description: Setup Link to create a SSO Connection
|
||||
---
|
||||
|
||||
# Setup Link (Enterprise SSO)
|
||||
|
||||
The Setup link is used to create a shareable link that can be used to create an SSO Connection without exposing any sensitive information.
|
||||
Let's go through the steps to create a new Setup link
|
||||
|
||||
## Create Setup Link
|
||||
|
||||
You can create a new Setup link for SSO from the Connections page using `New Setup Link` button
|
||||
|
||||

|
||||
|
||||
Another way is to go to the `Setup Links` section under `Enterprise SSO` menu and Click on Create New/New Setup Link button
|
||||
|
||||

|
||||
|
||||
The create Setup Link for SSO page looks like below
|
||||
|
||||

|
||||
|
||||
Once the link is created you can see the the link info section at the bottom
|
||||
|
||||

|
||||
|
||||
You can copy the link by clicking on the `Copy` button
|
||||
|
||||

|
||||
|
||||
### Regenerate Link
|
||||
|
||||
You can regenerate the link by clicking on `Regenerate` button
|
||||
|
||||

|
||||
|
||||
Once you confirm Regenerate action you will see the new setup link in the link info section
|
||||
|
||||

|
||||
|
||||
### Actions from Setup Link list page
|
||||
|
||||
#### You can perform `ACTIONS` like `Copy`, `View`, `Regenerate` & `Delete` from this page
|
||||
|
||||
Regenerate
|
||||
|
||||

|
||||
|
||||
Delete
|
||||
|
||||

|
||||
|
||||
### Setup Link page
|
||||
|
||||
When you open the setup link you will be landed on SSO Connection create section as there are no connections to show
|
||||
|
||||

|
||||
|
||||
### Create SSO Connection with Setup Link
|
||||
|
||||
You can create SSO Connection by filling the correct details
|
||||
|
||||

|
||||
|
||||
As you can see that setup link makes it super easy & safe to create SSO Connections.
|
@ -0,0 +1,648 @@
|
||||
---
|
||||
title: Directory Sync API Reference
|
||||
sidebar_label: API Reference
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# API Reference
|
||||
|
||||
The following guides provide information about the APIs and SDKs that are available for the Directory Sync service.
|
||||
|
||||
### Directory
|
||||
|
||||
#### Properties
|
||||
|
||||
- `name`: The name of the directory
|
||||
- `tenant`: The tenant ID of the tenant you want to create the directory for.
|
||||
- `product`: The product ID of the product you want to create the directory for.
|
||||
- `type`: The directory provider type. See the [Directory Providers](./providers) for more information.
|
||||
- `webhook_url`: The webhook URL to which the directory connection will POST the events.
|
||||
- `webhook_secret`: The webhook secret used to sign the webhook payload.
|
||||
|
||||
:::info
|
||||
The `tenant` and `product` should not contain the `:` character since we use it as a delimiter internally.
|
||||
:::
|
||||
|
||||
### Initialize Directory Sync
|
||||
|
||||
```javascript
|
||||
const opts = {
|
||||
externalUrl: 'https://my-cool-app.com',
|
||||
db: {
|
||||
engine: 'mongo',
|
||||
url: 'mongodb://localhost:27017/my-cool-app',
|
||||
},
|
||||
};
|
||||
|
||||
let directorySyncController;
|
||||
|
||||
// Please note that the initialization of @boxyhq/saml-jackson is async, you cannot run it at the top level.
|
||||
async function init() {
|
||||
const jackson = await require('@boxyhq/saml-jackson').controllers(opts);
|
||||
|
||||
directorySyncController = jackson.directorySyncController;
|
||||
}
|
||||
```
|
||||
|
||||
### Create a new directory
|
||||
|
||||
Create a new directory connection.
|
||||
|
||||
#### Request
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Node.js" default>
|
||||
|
||||
```javascript showLineNumbers
|
||||
const { data, error } = await directorySyncController.directories.create({
|
||||
name: 'App',
|
||||
tenant: 'boxyhq',
|
||||
product: 'jackson',
|
||||
type: 'onelogin-scim-v2',
|
||||
webhook_url: 'https://my-cool-app.com/webhook',
|
||||
webhook_secret: 'my-secret',
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="02" label="Shell">
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url http://localhost:5225/api/v1/directory-sync \
|
||||
--header 'Authorization: Api-Key secret' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"name": "App",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"type": "onelogin-scim-v2",
|
||||
"webhook_url": "https://my-cool-app.com/webhook",
|
||||
"webhook_secret": "my-secret"
|
||||
}'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Response
|
||||
|
||||
```javascript
|
||||
{
|
||||
"data": {
|
||||
"id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"name": "App",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"type": "onelogin-scim-v2",
|
||||
"log_webhook_events": false,
|
||||
"scim": {
|
||||
"path": "/api/scim/v2.0/58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"secret": "IJzAoevjD_liiiy-VkDtXg",
|
||||
"endpoint": "http://localhost:5225/api/scim/v2.0/58b5cd9dfaa39d47eb8f5f88631f9a629a232016"
|
||||
},
|
||||
"webhook": {
|
||||
"endpoint": "https://my-cool-app.com/webhook",
|
||||
"secret": "my-secret"
|
||||
}
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Get directories
|
||||
|
||||
Get the list of directories for the given tenant and product. A tenant can have multiple directories for same or different products.
|
||||
|
||||
#### Request
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Node.js" default>
|
||||
|
||||
```javascript showLineNumbers
|
||||
const tenant = 'boxyhq';
|
||||
const product = 'jackson';
|
||||
|
||||
const { data, error } =
|
||||
await directorySyncController.directories.getByTenantAndProduct(
|
||||
tenant,
|
||||
product
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="02" label="Shell">
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'http://localhost:5225/api/v1/directory-sync?tenant=boxyhq&product=jackson' \
|
||||
--header 'Authorization: Api-Key secret' \
|
||||
--header 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Response
|
||||
|
||||
```javascript
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"name": "App",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"type": "onelogin-scim-v2",
|
||||
"log_webhook_events": false,
|
||||
"scim": {
|
||||
"path": "/api/scim/v2.0/58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"secret": "IJzAoevjD_liiiy-VkDtXg",
|
||||
"endpoint": "http://localhost:5225/api/scim/v2.0/58b5cd9dfaa39d47eb8f5f88631f9a629a232016"
|
||||
},
|
||||
"webhook": {
|
||||
"endpoint": "https://my-cool-app.com/webhook",
|
||||
"secret": "my-secret"
|
||||
}
|
||||
}
|
||||
],
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Get a directory
|
||||
|
||||
Get the details of a directory by its unique id.
|
||||
|
||||
#### Request
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Node.js" default>
|
||||
|
||||
```javascript showLineNumbers
|
||||
const directoryId = '58b5cd9dfaa39d47eb8f5f88631f9a629a232016';
|
||||
|
||||
const { data, error } = await directorySyncController.directories.get(
|
||||
directoryId
|
||||
);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="02" label="Shell">
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'http://localhost:5225/api/v1/directory-sync/58b5cd9dfaa39d47eb8f5f88631f9a629a232016' \
|
||||
--header 'Authorization: Api-Key secret' \
|
||||
--header 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Response
|
||||
|
||||
```javascript
|
||||
{
|
||||
"data": {
|
||||
"id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"name": "App",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"type": "onelogin-scim-v2",
|
||||
"log_webhook_events": false,
|
||||
"scim": {
|
||||
"path": "/api/scim/v2.0/58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"secret": "IJzAoevjD_liiiy-VkDtXg",
|
||||
"endpoint": "http://localhost:5225/api/scim/v2.0/58b5cd9dfaa39d47eb8f5f88631f9a629a232016"
|
||||
},
|
||||
"webhook": {
|
||||
"endpoint": "https://my-cool-app.com/webhook",
|
||||
"secret": "my-secret"
|
||||
}
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### List directory users
|
||||
|
||||
List all the users in a directory.
|
||||
|
||||
#### Request
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Node.js" default>
|
||||
|
||||
```javascript showLineNumbers
|
||||
const tenant = 'boxyhq';
|
||||
const product = 'jackson';
|
||||
|
||||
const { data, error } = await directorySyncController.users
|
||||
.setTenantAndProduct(tenant, product)
|
||||
.getAll();
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="02" label="Shell">
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'http://localhost:5225/api/v1/directory-sync/users?tenant=boxyhq&product=jackson' \
|
||||
--header 'Authorization: Api-Key secret' \
|
||||
--header 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Response
|
||||
|
||||
```javascript
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "6296f71e-15fd-4af4-86ee-d6623b3ef1a4",
|
||||
"first_name": "Aswin",
|
||||
"last_name": "Venugopal",
|
||||
"email": "aswin@boxyhq.com",
|
||||
"active": true,
|
||||
"raw": {
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:core:2.0:User"
|
||||
],
|
||||
"userName": "aswin@boxyhq.com",
|
||||
"name": {
|
||||
"givenName": "Aswin",
|
||||
"familyName": "Venugopal",
|
||||
"honorificPrefix": "Sir"
|
||||
},
|
||||
"emails": [
|
||||
{
|
||||
"primary": true,
|
||||
"value": "aswin@boxyhq.com",
|
||||
"type": "work"
|
||||
}
|
||||
],
|
||||
"displayName": "Aswin Venugopal",
|
||||
"addresses": [
|
||||
{
|
||||
"primary": true,
|
||||
"postalCode": "123"
|
||||
}
|
||||
],
|
||||
"locale": "en-US",
|
||||
"externalId": "00u34iw1hm16RmjS95d7",
|
||||
"groups": [],
|
||||
"active": true,
|
||||
"id": "6296f71e-15fd-4af4-86ee-d6623b3ef1a4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"first_name": "Kiran",
|
||||
"last_name": "Krishnan",
|
||||
"email": "kiran@boxyhq.com",
|
||||
"active": true,
|
||||
"raw": {
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:core:2.0:User"
|
||||
],
|
||||
"userName": "kiran@boxyhq.com",
|
||||
"name": {
|
||||
"givenName": "Kiran",
|
||||
"familyName": "Krishnan"
|
||||
},
|
||||
"emails": [
|
||||
{
|
||||
"primary": true,
|
||||
"value": "kiran@boxyhq.com",
|
||||
"type": "work"
|
||||
}
|
||||
],
|
||||
"displayName": "Kiran Krishnan",
|
||||
"addresses": [
|
||||
{
|
||||
"primary": true,
|
||||
"region": "Kerala"
|
||||
}
|
||||
],
|
||||
"locale": "en-US",
|
||||
"externalId": "00u3e3cmpdDydXdzV5d7",
|
||||
"groups": [],
|
||||
"active": true,
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92"
|
||||
}
|
||||
}
|
||||
],
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Get a directory user
|
||||
|
||||
Get the details of a directory user.
|
||||
|
||||
#### Request
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Node.js" default>
|
||||
|
||||
```javascript showLineNumbers
|
||||
const tenant = 'boxyhq';
|
||||
const product = 'flex';
|
||||
const userId = 'ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92';
|
||||
|
||||
const users = await directorySyncController.users
|
||||
.setTenantAndProduct(tenant, product)
|
||||
.get(userId);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="02" label="Shell">
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'http://localhost:5225/api/v1/directory-sync/users/ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92?tenant=boxyhq&product=jackson' \
|
||||
--header 'Authorization: Api-Key secret' \
|
||||
--header 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Response
|
||||
|
||||
```javascript
|
||||
{
|
||||
"data": {
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"first_name": "Kiran",
|
||||
"last_name": "Krishnan",
|
||||
"email": "kiran@boxyhq.com",
|
||||
"active": true,
|
||||
"raw": {
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:core:2.0:User"
|
||||
],
|
||||
"userName": "kiran@boxyhq.com",
|
||||
"name": {
|
||||
"givenName": "Kiran",
|
||||
"familyName": "Krishnan"
|
||||
},
|
||||
"emails": [
|
||||
{
|
||||
"primary": true,
|
||||
"value": "kiran@boxyhq.com",
|
||||
"type": "work"
|
||||
}
|
||||
],
|
||||
"displayName": "Kiran Krishnan",
|
||||
"addresses": [
|
||||
{
|
||||
"primary": true,
|
||||
"region": "Kerala"
|
||||
}
|
||||
],
|
||||
"locale": "en-US",
|
||||
"externalId": "00u3e3cmpdDydXdzV5d7",
|
||||
"groups": [],
|
||||
"active": true,
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92"
|
||||
}
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### List directory groups
|
||||
|
||||
List all the groups in a directory.
|
||||
|
||||
#### Request
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Node.js" default>
|
||||
|
||||
```javascript showLineNumbers
|
||||
const tenant = 'boxyhq';
|
||||
const product = 'jackson';
|
||||
|
||||
const users = await directorySyncController.groups
|
||||
.setTenantAndProduct(tenant, product)
|
||||
.getAll();
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="02" label="Shell">
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'http://localhost:5225/api/v1/directory-sync/groups?tenant=boxyhq&product=jackson' \
|
||||
--header 'Authorization: Api-Key secret' \
|
||||
--header 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Response
|
||||
|
||||
```javascript
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "44d08c0e-d185-4a5e-80a6-b47a717ffaa5",
|
||||
"name": "Developers",
|
||||
"raw": {
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:core:2.0:Group"
|
||||
],
|
||||
"displayName": "Developers",
|
||||
"members": [
|
||||
{
|
||||
"value": "6296f71e-15fd-4af4-86ee-d6623b3ef1a4",
|
||||
"display": "aswin@boxyhq.com"
|
||||
},
|
||||
{
|
||||
"value": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"display": "kiran@boxyhq.com"
|
||||
}
|
||||
],
|
||||
"id": "44d08c0e-d185-4a5e-80a6-b47a717ffaa5"
|
||||
}
|
||||
}
|
||||
],
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Get a directory group
|
||||
|
||||
Get the details of a directory group.
|
||||
|
||||
#### Request
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Node.js" default>
|
||||
|
||||
```javascript showLineNumbers
|
||||
const tenant = 'boxyhq';
|
||||
const product = 'jackson';
|
||||
const groupId = '44d08c0e-d185-4a5e-80a6-b47a717ffaa5';
|
||||
|
||||
const users = await directorySyncController.groups
|
||||
.setTenantAndProduct(tenant, product)
|
||||
.get(groupId);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="02" label="Shell">
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'http://localhost:5225/api/v1/directory-sync/groups/44d08c0e-d185-4a5e-80a6-b47a717ffaa5?tenant=boxyhq&product=jackson' \
|
||||
--header 'Authorization: Api-Key secret' \
|
||||
--header 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Response
|
||||
|
||||
```javascript
|
||||
{
|
||||
"data": {
|
||||
"id": "44d08c0e-d185-4a5e-80a6-b47a717ffaa5",
|
||||
"name": "Developers",
|
||||
"raw": {
|
||||
"schemas": [
|
||||
"urn:ietf:params:scim:schemas:core:2.0:Group"
|
||||
],
|
||||
"displayName": "Developers",
|
||||
"members": [
|
||||
{
|
||||
"value": "6296f71e-15fd-4af4-86ee-d6623b3ef1a4",
|
||||
"display": "aswin@boxyhq.com"
|
||||
},
|
||||
{
|
||||
"value": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"display": "kiran@boxyhq.com"
|
||||
}
|
||||
],
|
||||
"id": "44d08c0e-d185-4a5e-80a6-b47a717ffaa5"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
"group_id": "44d08c0e-d185-4a5e-80a6-b47a717ffaa5",
|
||||
"user_id": "6296f71e-15fd-4af4-86ee-d6623b3ef1a4"
|
||||
},
|
||||
{
|
||||
"group_id": "44d08c0e-d185-4a5e-80a6-b47a717ffaa5",
|
||||
"user_id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92"
|
||||
}
|
||||
]
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Handle the Requests from Identity Providers
|
||||
|
||||
Make sure your application can handle the requests from Identity Providers.
|
||||
|
||||
#### Routes
|
||||
|
||||
Typically, you will want to add the following routes to your application to handle the requests. However, the `Methods` can vary for some Identity Providers.
|
||||
|
||||
| Route | Methods | Event |
|
||||
| ----------- | ---------- | ---------------------------------------------- |
|
||||
| /Users | POST | A new user has been assigned to a SCIM app |
|
||||
| /Users/:id | PUT, PATCH | A user information has been updated |
|
||||
| /Users/:id | DELETE | A user has been removed from a SCIM app |
|
||||
| /Groups | POST | A new group has been pushed |
|
||||
| /Groups/:id | PUT | Group name has been changed |
|
||||
| /Groups/:id | PATCH | User has been added to or removed from a group |
|
||||
| /Groups/:id | DELETE | Group has been removed |
|
||||
|
||||
#### User Requests
|
||||
|
||||
```javascript showLineNumbers
|
||||
const { data, status } = await directorySyncController.requests.handle(request);
|
||||
```
|
||||
|
||||
The shape of the `request` should be as follows:
|
||||
|
||||
```javascript
|
||||
{
|
||||
method: HTTPMethod;
|
||||
body?: any;
|
||||
directoryId: string;
|
||||
resourceId: string;
|
||||
resourceType: "users",
|
||||
apiSecret: string;
|
||||
query: {
|
||||
count?: number;
|
||||
startIndex?: number;
|
||||
filter?: string;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
#### Group Requests
|
||||
|
||||
Handling the group requests is similar to handling the user requests.
|
||||
|
||||
```javascript showLineNumbers
|
||||
const { data, status } = await directorySyncController.requests.handle(request);
|
||||
```
|
||||
|
||||
The shape of the `request` should be as follows:
|
||||
|
||||
```javascript
|
||||
{
|
||||
method: HTTPMethod;
|
||||
body?: any;
|
||||
directoryId: string;
|
||||
resourceId: string;
|
||||
resourceType: "groups",
|
||||
apiSecret: string;
|
||||
query: {
|
||||
count?: number;
|
||||
startIndex?: number;
|
||||
filter?: string;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
#### Callback Function
|
||||
|
||||
You can optionally pass a callback function as a second parameter to the handle method `requests.handle`. Jackson will invoke the callback with the event object as the first argument after handling the request. You can use the event object to determine the action to take.
|
||||
|
||||
```javascript showLineNumbers
|
||||
const callback = (event: DirectorySyncEvent) => {
|
||||
console.log(event);
|
||||
};
|
||||
|
||||
const { data, status } = await directorySyncController.requests.handle(
|
||||
request,
|
||||
callback
|
||||
);
|
||||
```
|
@ -0,0 +1,476 @@
|
||||
---
|
||||
title: Directory Sync Webhook Events
|
||||
sidebar_label: Events
|
||||
---
|
||||
|
||||
# Events
|
||||
|
||||
SAML Jackson uses webhooks to notify your application any time changes are made to directory, users, groups, and memberships.
|
||||
|
||||
## User Events
|
||||
|
||||
We'll notify you of the following 3 events related to users. Each event will be sent to the webhook URL you've configured in the Directory Sync app.
|
||||
|
||||
<details>
|
||||
<summary>user.created - New user has been assigned to the app.</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "user.created",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "038e767b-9bc6-4dbd-975e-fbc38a8e7d82",
|
||||
"first_name": "Deepak",
|
||||
"last_name": "Prabhakara",
|
||||
"email": "deepak@boxyhq.com",
|
||||
"active": true,
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
"userName": "deepak@boxyhq.com",
|
||||
"name": {
|
||||
"givenName": "Deepak",
|
||||
"familyName": "Prabhakara"
|
||||
},
|
||||
"emails": [
|
||||
{
|
||||
"primary": true,
|
||||
"value": "deepak@boxyhq.com",
|
||||
"type": "work"
|
||||
}
|
||||
],
|
||||
"title": "CEO",
|
||||
"displayName": "Deepak Prabhakara",
|
||||
"locale": "en-US",
|
||||
"externalId": "00u1ldzzogFkXFmvT5d7",
|
||||
"groups": [],
|
||||
"active": true,
|
||||
"id": "038e767b-9bc6-4dbd-975e-fbc38a8e7d82"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>user.updated - A user's properties has been updated.</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "user.updated",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"first_name": "Kiran",
|
||||
"last_name": "Krishnan",
|
||||
"email": "kiran@boxyhq.com",
|
||||
"active": true,
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
"userName": "kiran@boxyhq.com",
|
||||
"name": {
|
||||
"givenName": "Kiran",
|
||||
"familyName": "Krishnan"
|
||||
},
|
||||
"emails": [
|
||||
{
|
||||
"primary": true,
|
||||
"value": "kiran@boxyhq.com",
|
||||
"type": "work"
|
||||
}
|
||||
],
|
||||
"displayName": "Kiran Krishnan",
|
||||
"addresses": [
|
||||
{
|
||||
"primary": true,
|
||||
"region": "Kerala"
|
||||
}
|
||||
],
|
||||
"locale": "en-US",
|
||||
"externalId": "00u3e3cmpdDydXdzV5d7",
|
||||
"active": true,
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"groups": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>user.deleted - A user has been removed from the Directory Provider.</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "user.deleted",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"first_name": "Kiran",
|
||||
"last_name": "Krishnan",
|
||||
"email": "kiran@boxyhq.com",
|
||||
"active": false,
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
"userName": "kiran@boxyhq.com",
|
||||
"name": {
|
||||
"givenName": "Kiran",
|
||||
"familyName": "Krishnan"
|
||||
},
|
||||
"emails": [
|
||||
{
|
||||
"primary": true,
|
||||
"value": "kiran@boxyhq.com",
|
||||
"type": "work"
|
||||
}
|
||||
],
|
||||
"displayName": "Kiran Krishnan",
|
||||
"addresses": [
|
||||
{
|
||||
"primary": true,
|
||||
"region": "Kerala"
|
||||
}
|
||||
],
|
||||
"locale": "en-US",
|
||||
"externalId": "00u3e3cmpdDydXdzV5d7",
|
||||
"active": false,
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"groups": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
## Group Events
|
||||
|
||||
We'll notify you of the following 5 events related to groups and memberships. Each event will be sent to the webhook URL you've configured in the Directory Sync app.
|
||||
|
||||
<details>
|
||||
<summary>group.created - New group has been added to the app.</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "group.created",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6",
|
||||
"name": "dev",
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
|
||||
"displayName": "dev",
|
||||
"members": [],
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>group.updated - A group's properties has been updated.</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "group.updated",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6",
|
||||
"name": "developers",
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
|
||||
"displayName": "developers",
|
||||
"members": [],
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>group.deleted - A group has been removed from the app.</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "group.deleted",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6",
|
||||
"name": "developers",
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
|
||||
"displayName": "developers",
|
||||
"members": [],
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>group.user_added - A user has been added to a directory group.</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "group.user_added",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"first_name": "Kiran",
|
||||
"last_name": "Krishnan",
|
||||
"email": "kiran@boxyhq.com",
|
||||
"active": true,
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
"userName": "kiran@boxyhq.com",
|
||||
"name": {
|
||||
"givenName": "Kiran",
|
||||
"familyName": "Krishnan"
|
||||
},
|
||||
"emails": [
|
||||
{
|
||||
"primary": true,
|
||||
"value": "kiran@boxyhq.com",
|
||||
"type": "work"
|
||||
}
|
||||
],
|
||||
"displayName": "Kiran Krishnan",
|
||||
"addresses": [
|
||||
{
|
||||
"primary": true,
|
||||
"region": "Kerala"
|
||||
}
|
||||
],
|
||||
"locale": "en-US",
|
||||
"externalId": "00u3e3cmpdDydXdzV5d7",
|
||||
"active": true,
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"title": "Developer",
|
||||
"groups": []
|
||||
},
|
||||
"group": {
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6",
|
||||
"name": "developers",
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
|
||||
"displayName": "developers",
|
||||
"members": [],
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>group.user_removed - A user has been removed from a directory group.</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "group.user_removed",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"first_name": "Kiran",
|
||||
"last_name": "Krishnan",
|
||||
"email": "kiran@boxyhq.com",
|
||||
"active": true,
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
"userName": "kiran@boxyhq.com",
|
||||
"name": {
|
||||
"givenName": "Kiran",
|
||||
"familyName": "Krishnan"
|
||||
},
|
||||
"emails": [
|
||||
{
|
||||
"primary": true,
|
||||
"value": "kiran@boxyhq.com",
|
||||
"type": "work"
|
||||
}
|
||||
],
|
||||
"displayName": "Kiran Krishnan",
|
||||
"addresses": [
|
||||
{
|
||||
"primary": true,
|
||||
"region": "Kerala"
|
||||
}
|
||||
],
|
||||
"locale": "en-US",
|
||||
"externalId": "00u3e3cmpdDydXdzV5d7",
|
||||
"active": true,
|
||||
"id": "ebc31d6e-7d62-4f81-b9e5-eb5f1a04ee92",
|
||||
"title": "Developer",
|
||||
"groups": []
|
||||
},
|
||||
"group": {
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6",
|
||||
"name": "developers",
|
||||
"raw": {
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
|
||||
"displayName": "developers",
|
||||
"members": [],
|
||||
"id": "29e3adde-b4bb-45fc-bf65-2b44f29fd6f6"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
## Directory Events
|
||||
|
||||
We'll notify you of the following 4 events related to the directory connections.
|
||||
|
||||
To configure the webhook, you have to set the following environment variables.
|
||||
|
||||
- `WEBHOOK_URL` - The URL to which the webhook events will be sent.
|
||||
- `WEBHOOK_SECRET` - The secret key used to sign the webhook events.
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
dsync.created - New connection has been created.
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "dsync.created",
|
||||
"tenant": "boxyhq",
|
||||
"product": "demo",
|
||||
"data": {
|
||||
"id": "d8aa6c93-c960-4925-9b31-4a4d2ad3bb44",
|
||||
"name": "Okta Directory",
|
||||
"type": "okta-scim-v2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
dsync.deactivated - A connection has been deactivated.
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "dsync.deactivated",
|
||||
"tenant": "boxyhq",
|
||||
"product": "demo",
|
||||
"data": {
|
||||
"id": "d8aa6c93-c960-4925-9b31-4a4d2ad3bb44",
|
||||
"name": "Okta Directory",
|
||||
"type": "okta-scim-v2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
dsync.activated - A connection has been activated.
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "dsync.activated",
|
||||
"tenant": "boxyhq",
|
||||
"product": "demo",
|
||||
"data": {
|
||||
"id": "d8aa6c93-c960-4925-9b31-4a4d2ad3bb44",
|
||||
"name": "Okta Directory",
|
||||
"type": "okta-scim-v2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
dsync.deleted - A connection has been deleted.
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "dsync.deleted",
|
||||
"tenant": "boxyhq",
|
||||
"product": "demo",
|
||||
"data": {
|
||||
"id": "d8aa6c93-c960-4925-9b31-4a4d2ad3bb44",
|
||||
"name": "Okta Directory",
|
||||
"type": "okta-scim-v2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### How to determine whether a user has been deleted if the Identity Provider does not send a webhook event for user deletion?
|
||||
|
||||
To receive notifications when a user is deleted, it's important to note that not all Identity Providers send requests for this. However, you can listen for the `user.updated` event from SAML Jackson and examine the `active` property to determine whether a user has been deleted. In case the user is deleted, the `active` property will be assigned the value `false`.
|
||||
|
||||
### Which Identity Providers do not send an event for user deletion?
|
||||
|
||||
Following Identity Providers do not send `user.deleted` event:
|
||||
|
||||
- Okta
|
||||
- Azure AD
|
||||
|
||||
### Which SCIM version does SAML Jackson support?
|
||||
|
||||
At the moment, SAML Jackson supports SCIM version 2.0.
|
@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Examples & Resources (Directory Sync)
|
||||
sidebar_label: Examples & Resources
|
||||
description: Examples & Resources for our Directory Sync product
|
||||
---
|
||||
|
||||
# Examples & Resources (Directory Sync)
|
||||
|
||||
## Examples
|
||||
|
||||
- [Directory Sync with Next.js](https://github.com/boxyhq/jackson-examples/tree/main/apps/directory-sync)
|
||||
- [Directory Sync (embedded as a library) with Next.js](https://github.com/boxyhq/jackson-examples/tree/main/apps/directory-sync-embedded)
|
||||
|
||||
## Resources
|
||||
|
||||
- [SCIM 2.0 Protocol](https://datatracker.ietf.org/doc/html/rfc7644)
|
@ -0,0 +1,29 @@
|
||||
---
|
||||
title: Getting Started
|
||||
sidebar_label: Getting Started
|
||||
---
|
||||
|
||||
There are two ways to integrate the Directory Sync within your application.
|
||||
|
||||
## As a service
|
||||
|
||||
The advantage of running a separate service is that you get all of our UI tooling (like the Admin Portal) with the service. The disadvantage is that you have to manage the operations of a separate service.
|
||||
|
||||
**If you are not using Node.js then this is the only option available to you.**
|
||||
|
||||
Read more about [how to run the Jackson service](/docs/jackson/deploy/service)
|
||||
|
||||
Jackson use webhooks to notify your application any time changes are made to directory users and groups. You can use webhooks to trigger actions in your application, such as creating a new user in your application, or updating a user in your application based on the changes made in the directory.
|
||||
|
||||
## As an NPM library
|
||||
|
||||
This is available if you are already developing your application using Node.js.
|
||||
|
||||
The advantage of embedding Jackson as an NPM library is that you do not have to manage operations of a separate service.
|
||||
The disadvantage is that you do not readily get our UI tooling (like the Admin Portal) with this method.
|
||||
|
||||
```bash
|
||||
npm i --save @boxyhq/saml-jackson
|
||||
```
|
||||
|
||||
See the [API Reference](/docs/directory-sync/api-reference) to understand more about the available methods.
|
@ -0,0 +1,23 @@
|
||||
---
|
||||
title: Directory Sync Docs
|
||||
---
|
||||
|
||||
# Directory Sync
|
||||
|
||||
Directory sync helps organizations automate the provisioning and de-provisioning of their users. It is based on the System for Cross-domain Identity Management (SCIM) protocol.
|
||||
|
||||
As a result, it streamlines the user lifecycle management process by saving valuable organizational hours, creating a single truth source of the user identity data, and facilitating them to keep the data secure.
|
||||
|
||||
Directory Sync is part of our SAML Jackson service (and npm library) from v1.2.1 onwards. Follow the instructions in [SAML Jackson](../jackson/deploy/index.md) for details on deployment. Or check out our [GitHub repo](https://github.com/boxyhq/jackson#directory-sync).
|
||||
|
||||
We currently only support SCIM 2.0 protocol because SCIM 1.1 is deprecated and support will be discontinued on December 2nd, 2022. If you still need support for SCIM 1.1 and are unable to move away from it then please contact us.
|
||||
|
||||

|
||||
|
||||
## Overview
|
||||
|
||||
- [API Reference](api-reference)
|
||||
- [Admin Portal](../admin-portal/directory-sync)
|
||||
- [Webhook](webhooks)
|
||||
- [Events and Types](events)
|
||||
- [Directory Sync Providers](providers)
|
@ -0,0 +1,74 @@
|
||||
---
|
||||
title: Azure AD SCIM v2.0
|
||||
sidebar_label: Azure SCIM v2.0
|
||||
---
|
||||
|
||||
# Azure AD SCIM v2.0
|
||||
|
||||
The following guide will walk you through the process of configuring SAML Jackson to use the Azure AD SCIM v2.0 directory provider.
|
||||
|
||||
---
|
||||
|
||||
### Create Azure Application
|
||||
|
||||
Click **Azure Active Directory** from the Microsoft Azure Portal.
|
||||
|
||||

|
||||
|
||||
Click **Enterprise Applications** from the left navigation menu.
|
||||
|
||||

|
||||
|
||||
If your application is already created, choose it from the list and move to the section [Enable SCIM Provisioning](#enable-azure-scim-provisioning)
|
||||
|
||||
If you haven't created your application yet, click **New application** button.
|
||||
|
||||

|
||||
|
||||
From the next screen, click **Create your own application**, give your application a **name** and click the **Create** button.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### Enable Azure SCIM Provisioning
|
||||
|
||||
Click **Provisioning** from the left navigation menu then click **Get started**.
|
||||
|
||||

|
||||
|
||||
Select **Automatic** from the **Provisioning Mode** dropdown and enter the following information under **Admin Credentials** section:
|
||||
|
||||
- Tenant URL
|
||||
- Secret Token
|
||||
|
||||
Next, click the **Test Connection** button to test the connection to see if the credentials are correct, then click **Save** to save the credentials.
|
||||
|
||||

|
||||
|
||||
Expand the **Mappings** section and ensure group and user attribute mappings are enabled for your app. The default mapping should work.
|
||||
|
||||

|
||||
|
||||
Expand the **Settings** section and make the following changes:
|
||||
|
||||
- Select **Sync only assigned users and groups** from the **Scope** dropdown.
|
||||
- Confirm the **Provisioning Status** is set to **On**.
|
||||
|
||||

|
||||
|
||||
At this stage, you've successfully configured the Azure AD SCIM API integration.
|
||||
|
||||
---
|
||||
|
||||
### Assign Users
|
||||
|
||||
From your application, click the **Users and groups** from the left navigation menu and click **Add user/group**.
|
||||
|
||||

|
||||
|
||||
Select **None Selected** under the **Users**.
|
||||
|
||||
From the right side of the screen, select the users you want to assign to the app and click the **Select** button, then click **Assign** to those users to the app.
|
||||
|
||||

|
@ -0,0 +1,8 @@
|
||||
# Providers
|
||||
|
||||
SAML Jackson supports the following directory providers:
|
||||
|
||||
- [Azure SCIM v2.0](./azure)
|
||||
- [OneLogin SCIM v2.0](./onelogin)
|
||||
- [Okta SCIM v2.0](./okta)
|
||||
- [JumpCloud SCIM v2.0](./jumpcloud)
|
@ -0,0 +1,60 @@
|
||||
---
|
||||
title: JumpCloud SCIM v2.0
|
||||
sidebar_label: JumpCloud SCIM v2.0
|
||||
---
|
||||
|
||||
# JumpCloud SCIM v2.0
|
||||
|
||||
The following guide will walk you through the process of configuring SAML Jackson to use the JumpCloud SCIM v2.0 directory provider.
|
||||
|
||||
---
|
||||
|
||||
### Create JumpCloud SAML Application
|
||||
|
||||
JumpCloud only support configuring SCIM provisioning in an existing SAML application.
|
||||
|
||||
Choose an existing SAML application or create a new one. Click **SSO** from the left navigation menu and select your custom SAML application.
|
||||
|
||||

|
||||
|
||||
Click the tab **Identity Management** within your SAML application.
|
||||
|
||||
Unde the **SCIM Version**, choose **SCIM 2.0** and enter the following information:
|
||||
|
||||
- Base URL
|
||||
- Token Key
|
||||
- Test User Email
|
||||
|
||||
Click **Test Connection** to test the connection to see if the credentials are correct then click **Activate**.
|
||||
|
||||
Next click **Save** to save the settings.
|
||||
|
||||

|
||||
|
||||
At this stage, you've successfully configured the JumpCloud SCIM app.
|
||||
|
||||
---
|
||||
|
||||
### Assign Users & Push Groups
|
||||
|
||||

|
||||
|
||||
Click the tab **User Groups** within your SAML application.
|
||||
|
||||
You can see the all the groups that are available, select the groups you want to sync and click **Save**.
|
||||
|
||||
If no existing groups are available, click **User Groups** from the left navigation menu and click plus icon to create a new group.
|
||||
|
||||
Give the group a name.
|
||||
|
||||

|
||||
|
||||
Select the **Users** tab and choose the users you want to assign to the group.
|
||||
|
||||

|
||||
|
||||
Next select the **Applications** tab and choose the app you want to assign the group to.
|
||||
|
||||

|
||||
|
||||
At this stage, you've successfully assigned users and pushed the groups.
|
@ -0,0 +1,81 @@
|
||||
---
|
||||
title: Okta SCIM v2.0
|
||||
sidebar_label: Okta SCIM v2.0
|
||||
---
|
||||
|
||||
# Okta SCIM v2.0
|
||||
|
||||
The following guide will walk you through the process of configuring SAML Jackson to use the Okta as a directory sync provider.
|
||||
|
||||
---
|
||||
|
||||
### Create Okta Application
|
||||
|
||||
Click **Applications** from the left navigation menu and click **Browse App Catalog** button.
|
||||
|
||||

|
||||
|
||||
Search for **SCIM 2.0 Test App (Oauth Bearer Token)** from the search box and choose the app called **SCIM 2.0 Test App (Oauth Bearer Token)**.
|
||||
|
||||

|
||||
|
||||
From the app page, click the **Add Integration** button.
|
||||
|
||||

|
||||
|
||||
Give the app a name and click the **Next** button. Click **Done** to finish the creation of the app.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### Enable Okta SCIM Provisioning
|
||||
|
||||
In your application, click the **Provisioning** tab and click **Configure API Integration**.
|
||||
|
||||

|
||||
|
||||
Check the **Enable API Integration** checkbox and enter the following information:
|
||||
|
||||
- SCIM 2.0 Base URL
|
||||
- OAuth Bearer Token
|
||||
|
||||
You'll receive these information from Jackson when you create the directory sync connection either via the API or the Admin Portal.
|
||||
|
||||
Click **Test API Creditentials** to test the connection to see if the credentials are correct then click the **Save** to save the credentials.
|
||||
|
||||

|
||||
|
||||
You'll see a new setting page, click **To App** and enable the following settings:
|
||||
|
||||

|
||||
|
||||
At this stage, you've successfully configured the Okta SCIM API integration.
|
||||
|
||||
---
|
||||
|
||||
### Assign Users
|
||||
|
||||
In your application, click the **Assignments** tab and select **Assign to People** from the dropdown **Assign**.
|
||||
|
||||

|
||||
|
||||
Select users you want to assign to the app and click the **Assign** button.
|
||||
|
||||

|
||||
|
||||
After you click the **Assign** button, you'll see a new popup window with various fields. Confirm the field values and click the **Save and Go Back** button.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### Push Groups
|
||||
|
||||
Navigate to the tab **Push Groups** and select **Find group by name** from the dropdown **Push Groups**.
|
||||
|
||||

|
||||
|
||||
Find the group you want to assign to the app and click the **Save** button.
|
||||
|
||||

|
@ -0,0 +1,121 @@
|
||||
---
|
||||
title: OneLogin SCIM v2.0
|
||||
sidebar_label: OneLogin SCIM v2.0
|
||||
---
|
||||
|
||||
# OneLogin SCIM v2.0
|
||||
|
||||
The following guide will walk you through the process of configuring SAML Jackson to use the OneLogin SCIM v2.0 directory provider.
|
||||
|
||||
---
|
||||
|
||||
### Create OneLogin Application
|
||||
|
||||
Click **Applications** from the top navigation menu and click **Add App** button.
|
||||
|
||||

|
||||
|
||||
Search for **SCIM** from the search box and choose the app called **SCIM Provisioner with SAML (SCIM V2 Enterprise)** from the list of apps.
|
||||
|
||||

|
||||
|
||||
Give the app a name and click the **Save** button.
|
||||
|
||||

|
||||
|
||||
At this stage, you've successfully created the OneLogin SCIM app.
|
||||
|
||||
---
|
||||
|
||||
### Enable OneLogin SCIM Provisioning
|
||||
|
||||
In your application, click the **Configuration** tab on the left.
|
||||
|
||||
Enter the following information:
|
||||
|
||||
- SCIM Base URL
|
||||
- SCIM Bearer Token
|
||||
|
||||
You'll receive these information from Jackson when you create the directory sync connection either via the API or the Admin Portal.
|
||||
|
||||
Click the button **Enable** to test the connection to see if the credentials are correct and click the button to **Save** to save the creditentials.
|
||||
|
||||

|
||||
|
||||
Next click the **Provisioning** tab and check the **Enable provisioning** checkbox. Click the **Save** button to save the changes.
|
||||
|
||||

|
||||
|
||||
Next click the **Parameters** tab and select the row **Groups** from the table.
|
||||
|
||||

|
||||
|
||||
In the popup window, check the box **Include in User Provisioning** and click the **Save** button.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
### Assign Users
|
||||
|
||||
In order to assign users to your app, select **Users** from the top navigation menu and choose the user you want to assign to the app.
|
||||
|
||||
From the user page, click the **Application** tab on the left and click the plus sign.
|
||||
|
||||

|
||||
|
||||
A popup window will show you the list of apps that you can assign the user to. Select the app you created earlier and click the **Continue** button.
|
||||
|
||||

|
||||
|
||||
Click **Save** on the next modal window to confirm the assignment.
|
||||
|
||||

|
||||
|
||||
Depending on your configuration, You may have to approve the assignment.
|
||||
|
||||
If you see a text **Pending** in the table, click that text. That'll bring up a modal window, click the button **Approve** to approve the assignment.
|
||||
|
||||

|
||||
|
||||
At this point, the user will be assigned to the app.
|
||||
|
||||
---
|
||||
|
||||
### Push Groups
|
||||
|
||||
In order to push groups to your app, you've to create a new **Role** in your app.
|
||||
|
||||
In the top navigation, select **Users** and then **Roles** from the dropdown.
|
||||
|
||||
Click **New Role** to create a new role.
|
||||
|
||||

|
||||
|
||||
Enter a name for the role, select the app you created earlier and click the **Save** button.
|
||||
|
||||

|
||||
|
||||
Click the **Users** tab for the role and search for the user you want to assign the role to.
|
||||
|
||||
Click the button **Add To Role** to assign the user to the role and click the **Save** button.
|
||||
|
||||

|
||||
|
||||
Click **Save** in the next modal to confirm the assignment.
|
||||
|
||||

|
||||
|
||||
Go back to your app and click the **Rule** tab on the left and click the **Add Rule** button.
|
||||
|
||||
Give the rule a name. Under the **Actions**, select the **Set Groups in your-app-name** from the dropdown, then select for each **role** with values that matches **your-app-name**. Click the **Save** button.
|
||||
|
||||

|
||||
|
||||
Click the **Users** tab on the left, you may see **Pending** provisions in the table. Click that text to approve the assignment.
|
||||
|
||||

|
||||
|
||||
Click **Approve** in the next modal to confirm the assignment.
|
||||
|
||||

|
@ -0,0 +1,120 @@
|
||||
---
|
||||
title: Directory Sync Webhooks
|
||||
sidebar_label: Webhooks
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Webhooks
|
||||
|
||||
A webhook is an HTTP request, triggered by an event in a source system and sent to a destination system (Eg: your app), often with a payload of data.
|
||||
|
||||
SAML Jackson use webhooks to notify your application any time changes are made to directory users and groups. You can use webhooks to trigger actions in your application, such as creating a new user in your application, or updating a user in your application based on the changes made in the directory.
|
||||
|
||||
## Configure Webhooks
|
||||
|
||||
SAML Jackson allows you to configure a webhook and secret while creating a directory sync connection either in the Admin Portal or the API. You can change the webhook and secret at any time.
|
||||
|
||||
- [Admin Portal](../admin-portal/directory-sync)
|
||||
- [API Reference](api-reference#create-a-new-directory)
|
||||
|
||||
## Receive Events
|
||||
|
||||
SAML Jackson will make a POST request to your webhook endpoint when a change is made to a directory user or group. Your webhook endpoint should be able to receive the webhook request and respond with a 200 status code.
|
||||
|
||||
You can start receiving events in your app using the below steps:
|
||||
|
||||
- Create a webhook endpoint as an HTTP endpoint (URL) on your server.
|
||||
- Create a directory sync connection and configure a webhook endpoint.
|
||||
- Configure the SCIM app on your Identity Provider.
|
||||
- Handle the webhook request and respond with a 200 status code.
|
||||
|
||||
To see the full list of events, please see the [Events and Types](events) page.
|
||||
|
||||
Here is a sample webhook request look like:
|
||||
|
||||
```json
|
||||
POST /your-webhook-endpoint
|
||||
Content-Type: application/json
|
||||
BoxyHQ-Signature: t=xxx,s=xxxx
|
||||
|
||||
{
|
||||
"directory_id": "58b5cd9dfaa39d47eb8f5f88631f9a629a232016",
|
||||
"event": "user.created",
|
||||
"tenant": "boxyhq",
|
||||
"product": "jackson",
|
||||
"data": {
|
||||
"id": "038e767b-9bc6-4dbd-975e-fbc38a8e7d82",
|
||||
"first_name": "Deepak",
|
||||
"last_name": "Prabhakara",
|
||||
"email": "deepak@boxyhq.com",
|
||||
"active": true,
|
||||
"raw": {...}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::caution
|
||||
If the webhook request fails, SAML Jackson will not retry the webhook request. A log will be created in the SAML Jackson Admin Portal if the you've enabled the webhook event logging.
|
||||
:::
|
||||
|
||||
## Secure Webhooks
|
||||
|
||||
Use the webhook signature (**BoxyHQ-Signature**) to verify the webhook request is from SAML Jackson. The signature is generated using the **webhook secret** you configured in the directory sync connection.
|
||||
|
||||
Signature contains comma separated values of the following:
|
||||
|
||||
- **t** The timestamp of the webhook request.
|
||||
- **s** The signature of the webhook request.
|
||||
|
||||
An example of the webhook signature is below:
|
||||
|
||||
```
|
||||
BoxyHQ-Signature: t=1545010989801,s=xxxx
|
||||
```
|
||||
|
||||
## Verify Webhooks Signature
|
||||
|
||||
You can verify the webhook signature by using the following steps:
|
||||
|
||||
- Extract the **t** and **s** values from the webhook signature.
|
||||
- Create the signed payload string by concatenating:
|
||||
- The timestamp (t)
|
||||
- The character `.`
|
||||
- The actual JSON payload
|
||||
- Compute the `HMAC-SHA256` hash of the signed payload string using your webhook secret.
|
||||
- Compare the signature in the request header with the computed signature.
|
||||
|
||||
Once the signature is verified, you can use the webhook payload to perform any action in your application.
|
||||
|
||||
```javascript showLineNumbers
|
||||
// Your webhook secret
|
||||
const secret = 'your-secret-here';
|
||||
|
||||
// The signature header from the webhook request.
|
||||
const signatureHeader =
|
||||
't=1657016083300,s=9ece981128a8f2a96f95e3d0be68c37b825d5c15f5b8982e0b7e198a76621866';
|
||||
|
||||
// JSON body from the webhook request.
|
||||
const body = {...}
|
||||
|
||||
const [t, s] = signatureHeader.split(',');
|
||||
|
||||
const signature = t.split('=')[1];
|
||||
const timestamp = s.split('=')[1];
|
||||
|
||||
const signedPayload = `${timestamp}.${JSON.stringify(body)}`;
|
||||
|
||||
const expectedSignature = crypto
|
||||
.createHmac('sha256', secret)
|
||||
.update(signedPayload)
|
||||
.digest('hex');
|
||||
|
||||
// Compare the expectedSignature to the signature
|
||||
if(signature === expectedSignature) {
|
||||
// The webhook request is valid
|
||||
} else {
|
||||
// The webhook request is invalid
|
||||
}
|
||||
```
|
@ -0,0 +1,21 @@
|
||||
# Container Signing and Verification
|
||||
|
||||
Jackson container images are signed and can be verified using [cosign](https://github.com/sigstore/cosign).
|
||||
|
||||
## Fetching our public key
|
||||
|
||||
You can use [oras](https://oras.land/docs/category/cli) (or a similar OCI artifacts tool) to fetch our public key or download it from our website [here](https://boxyhq.com/.well-known/cosign.pub).
|
||||
|
||||
```bash
|
||||
oras pull ghcr.io/boxyhq/cosign.pub:latest
|
||||
```
|
||||
|
||||
## Container verification
|
||||
|
||||
**Note:** This is supported for all versions >=1.6.0
|
||||
|
||||
Our container images are hosted on [Docker Hub](https://hub.docker.com/r/boxyhq/jackson/tags). You can verify it by using the following command.
|
||||
|
||||
```bash
|
||||
cosign verify --key cosign.pub boxyhq/jackson:<version>
|
||||
```
|
@ -0,0 +1,374 @@
|
||||
---
|
||||
title: Environment Variables (Enterprise SSO)
|
||||
sidebar_label: Environment Variables
|
||||
description: Environment Variables for Enterprise SSO
|
||||
---
|
||||
|
||||
# Environment Variables
|
||||
|
||||
The env vars are only applicable to the Jackson service. If you are using the npm library then look for the options below when initializing the library.
|
||||
|
||||
## General configuration
|
||||
|
||||
### **HOST_URL**
|
||||
|
||||
The URL to bind to.
|
||||
Default: `localhost`
|
||||
|
||||
### **PORT**
|
||||
|
||||
The port to bind to.
|
||||
Default: `5225`
|
||||
|
||||
### **EXTERNAL_URL**
|
||||
|
||||
The public URL to reach this service. This is used internally to construct the callback url at which the SAML/OIDC IdP sends back the authorization response.
|
||||
|
||||
Default: `http://{HOST_URL}:{PORT}`
|
||||
|
||||
NPM library option: `externalUrl`
|
||||
|
||||
### **JACKSON_API_KEYS**
|
||||
|
||||
A comma separated list of API keys that will be validated when serving the API requests for SSO connection (`/api/v1/connections`) and Directory Sync (`/api/v1/directory-sync`).
|
||||
|
||||
For example `JACKSON_API_KEYS=key1,key2,key3`
|
||||
|
||||
The API requests will then need to specify an `Authorization` header which contains one of the API keys above in this format: `Api-Key key1`
|
||||
|
||||
### **SAML_AUDIENCE**
|
||||
|
||||
The value of this setting (same as SP EntityID of Jackson) allows the Jackson instance to verify that it is the intended recipient of a SAML response. The same value is also set in the SAML App created on the IdP end by your customers. Once set do not change this value unless you get your customers to reconfigure their SAML App again. It is case-sensitive. This does not have to be a real URL.
|
||||
|
||||
Default: `https://saml.boxyhq.com`
|
||||
|
||||
NPM library option: `samlAudience`
|
||||
|
||||
### **samlPath**
|
||||
|
||||
> **_NOTE:_** This is only applicable to our npm library.
|
||||
|
||||
The ACS path at which the [saml response](./npm-library#handle-saml-response) is sent back from the SAML IdP. Set this when using the npm package.
|
||||
|
||||
NPM library option: `samlPath`
|
||||
|
||||
For example: `/api/oauth/saml`
|
||||
|
||||
### **oidcPath**
|
||||
|
||||
> **_NOTE:_** This is only applicable to our npm library.
|
||||
|
||||
The `redirect_uri` at which the Authorization response is sent back from the OpenID Connect IdP. Set this when using the npm package.
|
||||
|
||||
NPM library option: `oidcPath`
|
||||
|
||||
For example: `/api/oauth/oidc`
|
||||
|
||||
### **IDP_DISCOVERY_PATH**
|
||||
|
||||
This is the path for showing the IdP Selection screen in case there are multiple SSO Connections for the same `tenant` and `product`.
|
||||
This path is also used to show the App Selection screen in the case of IdP-initiated SAML login (Different apps using the same SAML IdP).
|
||||
Set this when using the npm package.
|
||||
|
||||
NPM library option: `idpDiscoveryPath`
|
||||
|
||||
For example: `/idp/select` - You can find an implementation of IdP/App Selection at https://github.com/boxyhq/jackson/blob/main/pages/idp/select.tsx.
|
||||
|
||||
### **CLIENT_SECRET_VERIFIER**
|
||||
|
||||
When `tenant` and `product` are used for the SAML flow (and PKCE is not being used) then we use `dummy` as placeholders for `client_id` and `client_secret`. This is not a security issue because SAML is tenanted and hence your Identity Provider will block access to anyone trying to log into your SAML tenant. However for additional security you should set `CLIENT_SECRET_VERIFIER` to a random secret and use that value as the `client_secret` during the OAuth 2.0 flow.
|
||||
|
||||
Default: `dummy`
|
||||
|
||||
NPM library option: `clientSecretVerifier`
|
||||
|
||||
### **IDP_ENABLED**
|
||||
|
||||
Set to true to enable IdP initiated login for SAML. SP initiated login is the only recommended flow but you might have to support IdP login at times.
|
||||
|
||||
Default: `false`
|
||||
|
||||
NPM library option: `idpEnabled`
|
||||
|
||||
### **PUBLIC_KEY**
|
||||
|
||||
This is the public key of the private key used to sign the SAML requests. Jackson expects the public key to be base64 encoded.
|
||||
|
||||
NPM library option: `certs.publicKey`
|
||||
|
||||
### **PRIVATE_KEY**
|
||||
|
||||
This is the private key used to sign the SAML requests. Jackson expects the private key to be base64 encoded.
|
||||
|
||||
NPM library option: `certs.privateKey`
|
||||
|
||||
To generate a private key and public key pair you can use the following command:
|
||||
|
||||
```bash
|
||||
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out public.crt -sha256 -days 365 -nodes
|
||||
|
||||
# Convert the public key to base64
|
||||
cat public.crt | base64
|
||||
|
||||
# Convert the private key to base64
|
||||
cat key.pem | base64
|
||||
```
|
||||
|
||||
## OpenID configuration
|
||||
|
||||
For supporting OpenID flow, we need to set the algorithm and keys used to sign the ID token JWT.
|
||||
|
||||
### **OPENID_JWS_ALG**
|
||||
|
||||
The algorithm used to sign the id_token. Jackson uses [jose](https://github.com/panva/jose) to create the ID token. Supported algorithms can be found at https://github.com/panva/jose/issues/114#digital-signatures.
|
||||
|
||||
Default: `RS256`
|
||||
|
||||
NPM library option: `openid.jwsAlg`
|
||||
|
||||
### **OPENID_RSA_PRIVATE_KEY**
|
||||
|
||||
Base64 value of private key.
|
||||
To generate one:
|
||||
|
||||
```bash
|
||||
openssl genrsa -out private-key.pem 3072
|
||||
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private-key.pem -out private_key.pem
|
||||
cat private_key.pem | base64
|
||||
```
|
||||
|
||||
NPM library option: `openid.jwtSigningKeys.private`
|
||||
|
||||
### **OPENID_RSA_PUBLIC_KEY**
|
||||
|
||||
Base64 value of public key.
|
||||
You can generate the public key from the private key as shown below:
|
||||
|
||||
```bash
|
||||
openssl rsa -in private_key.pem -pubout -out public_key.pem
|
||||
cat public_key.pem | base64
|
||||
```
|
||||
|
||||
NPM library option: `openid.jwtSigningKeys.public`
|
||||
|
||||
## Database configuration
|
||||
|
||||
### **DB_ENGINE**
|
||||
|
||||
Supported values are `redis`, `sql`, `mongo`, `mem`, `planetscale`, `dynamodb`
|
||||
|
||||
Default: `sql`
|
||||
|
||||
NPM library option: `db.engine`
|
||||
|
||||
> **_NOTE:_** If you are using DynamoDB then you also need to set `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. For additional options like region and capacity units check [this section](#db_dynamodb_region)
|
||||
|
||||
> **_NOTE:_** `mem` DB (In memory database) is useful to test the Jackson setup locally and is not intended for production. In a serverless deployment like Vercel, the mem DB won't persist across API calls since each call is a fresh lambda invocation with an entirely new context.
|
||||
|
||||
### **DB_TYPE**
|
||||
|
||||
Only needed when DB_ENGINE is sql. Supported values are `postgres`, `mysql`, `mariadb`, `mssql`
|
||||
|
||||
Default: `postgres`
|
||||
|
||||
NPM library option: `db.type`
|
||||
|
||||
### **DB_URL**
|
||||
|
||||
The database URL to connect to. If you are using self-signed certificates then pass `sslmode=noverify` instead of `sslmode=require` in the `DB_URL`. This is because self-signed certs will be rejected as unauthorized in strict mode. Also, set `DB_SSL=true` and `DB_SSL_REJECT_UNAUTHORIZED=false` (see env vars below for more details).
|
||||
|
||||
Example: `postgres://postgres:postgres@localhost:5432/postgres` or `postgres://postgres:postgres@localhost:5432/postgres?sslmode=no-verify`
|
||||
|
||||
For `mssql` the URL takes the form of `sqlserver://localhost:1433;database=<db name>;username=<username>;password=<password>;encrypt=true`
|
||||
|
||||
> **_NOTE:_** If you are using DynamoDB then you also need to set `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. For additional options like region and capacity units check [this section](#db_dynamodb_region)
|
||||
|
||||
NPM library option: `db.url`
|
||||
|
||||
### **DB_SSL**
|
||||
|
||||
This needs to be set to `true` if you are using SSL with your database (You should definitely be using SSL if the database needs to be access via a public url).
|
||||
|
||||
Default: `false`
|
||||
|
||||
### **DB_SSL_REJECT_UNAUTHORIZED**
|
||||
|
||||
If you are using a self-signed certificate then set this to `false`, otherwise it will be rejected due to Certificate Authority checks.
|
||||
|
||||
Default: `true`
|
||||
|
||||
### **DB_TTL**
|
||||
|
||||
TTL for the code, session and token stores (in seconds)
|
||||
|
||||
Default: `300`
|
||||
|
||||
NPM library option: `db.ttl`
|
||||
|
||||
### **DB_CLEANUP_LIMIT**
|
||||
|
||||
Limit cleanup of TTL entries to this number
|
||||
|
||||
Default: `1000`
|
||||
|
||||
NPM library option: `db.cleanupLimit`
|
||||
|
||||
### **DB_ENCRYPTION_KEY**
|
||||
|
||||
To encrypt data at rest specify a 32 character key
|
||||
|
||||
You can use openssl to generate a random 32 character key:
|
||||
|
||||
```bash
|
||||
openssl rand -base64 24
|
||||
```
|
||||
|
||||
NPM library option: `db.encryptionKey`
|
||||
|
||||
### **PGSSLMODE**
|
||||
|
||||
If you use Heroku to deploy Postgres (or use self-signed certs for Postgres) then set this to `no-verify`. See [Heroku docs](https://devcenter.heroku.com/articles/connecting-heroku-postgres#connecting-in-node-js) for more details
|
||||
|
||||
### **DB_DYNAMODB_REGION**
|
||||
|
||||
If you are using DynamoDB then you can specify the region.
|
||||
|
||||
Default: `us-east-1`
|
||||
|
||||
NPM library option: `db.dynamodb.region`
|
||||
|
||||
### **DB_DYNAMODB_RCUS**
|
||||
|
||||
If you are using DynamoDB then you can specify the read capacity units. Check [AWS docs](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html) for more details
|
||||
|
||||
Default: 5
|
||||
|
||||
NPM library option: `db.dynamodb.readCapacityUnits`
|
||||
|
||||
### **DB_DYNAMODB_WCUS**
|
||||
|
||||
If you are using DynamoDB then you can specify the write capacity units.
|
||||
|
||||
Default: 5
|
||||
|
||||
NPM library option: `db.dynamodb.writeCapacityUnits`
|
||||
|
||||
## Webhook configuration
|
||||
|
||||
### **WEBHOOK_URL**
|
||||
|
||||
Specify a webhook URL to receive events about sso and directory connections.
|
||||
|
||||
NPM library option: `webhook.endpoint`
|
||||
|
||||
### **WEBHOOK_SECRET**
|
||||
|
||||
Specify a secret to be used to sign the webhook payload. This is used to verify the authenticity of the webhook payload.
|
||||
|
||||
NPM library option: `webhook.secret`
|
||||
|
||||
Both the `WEBHOOK_URL` and `WEBHOOK_SECRET` are required to enable webhook events.
|
||||
|
||||
## Pre-loaded Connections
|
||||
|
||||
### **PRE_LOADED_CONNECTION**
|
||||
|
||||
If you only need a single tenant or a handful of pre-configured tenants then this config will help you read and load IdP (both OpenID and SAML)connections. It works well with the mem DB engine so you don't have to configure any external databases for this to work (though it works with those as well). This is a path (absolute or relative) to a directory that contains files organized in the format described in the next section. Check [this section](./pre-loaded-connections.md) for more details
|
||||
|
||||
NPM library option: `preLoadedConnection`
|
||||
|
||||
## Opentelemetry configuration
|
||||
|
||||
Jackson supports observability via OpenTelemetry. The following env vars are available for configuration (along with the rest of the [supported ones](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md))
|
||||
|
||||
### **OTEL_EXPORTER_OTLP_ENDPOINT** or **OTEL_EXPORTER_OTLP_METRICS_ENDPOINT**
|
||||
|
||||
Target URL to which the exporter is going to send metrics.
|
||||
|
||||
Example: `https://ingest.lightstep.com:443/metrics/otlp/v0.6`
|
||||
|
||||
### **OTEL_EXPORTER_OTLP_HEADERS** or **OTEL_EXPORTER_OTLP_METRICS_HEADERS**
|
||||
|
||||
Headers relevant for the endpoint, useful for specifying authentication details for providers.
|
||||
|
||||
Example: `lightstep-access-token=<token>,...`
|
||||
|
||||
### **OTEL_EXPORTER_OTLP_PROTOCOL** or **OTEL_EXPORTER_OTLP_METRICS_PROTOCOL**
|
||||
|
||||
The transport protocol. Options MUST be one of: `grpc`, `http/protobuf` or `http/json`.
|
||||
|
||||
### **OTEL_EXPORTER_DEBUG**
|
||||
|
||||
Set this to `true` to enable debug logs for Opentelemetry. This is only meant for purposes of debugging otel locally.
|
||||
|
||||
## Admin Portal configuration
|
||||
|
||||
Below variables are used to enable [Magic link](https://next-auth.js.org/providers/email) based authentication for Admin Portal. The **SMTP\_** variables are used for sending email which contain the magic link (one-time use) for sign in.
|
||||
|
||||
### **SMTP_HOST**
|
||||
|
||||
The SMTP host like `smtp.example.com`.
|
||||
|
||||
### **SMTP_PORT**
|
||||
|
||||
The SMTP server port like `587`.
|
||||
|
||||
### **SMTP_USER**
|
||||
|
||||
Username for the SMTP server.
|
||||
|
||||
### **SMTP_PASSWORD**
|
||||
|
||||
Password for the SMTP server.
|
||||
|
||||
### **SMTP_FROM**
|
||||
|
||||
_From_ address used to send mail like: `noreply@example.com`.
|
||||
|
||||
### **NEXTAUTH_URL**
|
||||
|
||||
When running locally this will point to the local server: `http://localhost:5225`. When deploying to production, set this to the canonical URL of the site. More details [here](https://next-auth.js.org/configuration/options#nextauth_url).
|
||||
|
||||
### **NEXTAUTH_SECRET**
|
||||
|
||||
Set this to a random string. You can use `openssl rand -base64 32` to get one. This secret is used to encrypt JWT and hash the email verification token. More details [here](https://next-auth.js.org/configuration/options#nextauth_secret).
|
||||
|
||||
### **NEXTAUTH_ACL**
|
||||
|
||||
Set this to a comma separated string of email addresses or glob patterns like: `tonystark@gmail.com,*@marvel.com`. Access will be denied to email addresses which don't match. If you don't specify any value access is denied to all.
|
||||
|
||||
### **NEXTAUTH_ADMIN_CREDENTIALS**
|
||||
|
||||
Set this to a comma separated string of the pattern `email:password` to enable login to the Admin Portal, for example `NEXTAUTH_ADMIN_CREDENTIALS=deepak@boxyhq.com:Password123`. If you don't specify any value access is denied to all.
|
||||
|
||||
### **ADMIN_PORTAL_SSO_TENANT**
|
||||
|
||||
This will be used as the tenant for the SSO connections (added from Settings tab) used to login into the Admin portal itself. Set this to a value that is less likely to conflict with the main Enterprise SSO connections.
|
||||
|
||||
Default: `_jackson_boxyhq`
|
||||
|
||||
### **ADMIN_PORTAL_SSO_PRODUCT**
|
||||
|
||||
This will be used as the product for the SSO connections (added from Settings tab) used to login into the Admin portal itself. Set this to a value that is less likely to conflict with the main Enterprise SSO connections.
|
||||
|
||||
Default: `_jackson_admin_portal`
|
||||
|
||||
### **RETRACED_HOST_URL**
|
||||
|
||||
If you'd like to use the Admin Portal to manage our Audit Logs service ([Retraced](https://github.com/retracedhq/retraced)) then set this env var to the URL of the service.
|
||||
|
||||
### **RETRACED_EXTERNAL_URL**
|
||||
|
||||
If you'd like to use the Admin Portal to manage our Audit Logs service ([Retraced](https://github.com/retracedhq/retraced)) then set this env var to the Public URL of the service. If this is the same as `RETRACED_HOST_URL` above then you can skip this and it will default to the value of `RETRACED_HOST_URL`.
|
||||
|
||||
Default: It is set to `RETRACED_HOST_URL` if `RETRACED_EXTERNAL_URL` is not defined.
|
||||
|
||||
### **RETRACED_ADMIN_ROOT_TOKEN**
|
||||
|
||||
you need to set the admin root token for Retraced so that we can connect to Retraced and fetch projects and audit logs.
|
||||
|
||||
## Anonymous Analytics
|
||||
|
||||
### **BOXYHQ_NO_TELEMETRY** or **DO_NOT_TRACK**
|
||||
|
||||
Set one of these to `1` or `true` to turn off our anonymous analytics. We only track usage events once per day and it does not contain any information that can identify you in any form.
|
@ -0,0 +1,19 @@
|
||||
---
|
||||
title: Getting Started with SAML Jackson
|
||||
description: Getting Started with SAML Single Sign-On authentication
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
SAML Jackson can be used with any web application to integrate the **Single Sign-On (SSO) authentication**.
|
||||
|
||||
There are two ways to integrate SAML Jackson with an application. Depending on your use case, you can choose either one of them.
|
||||
|
||||
## As a [separate service](./service.md)
|
||||
|
||||
The advantage of running a separate service is that you get all of our UI tooling (like the Admin Portal) with the service. The disadvantage is that you have to manage the operations of a separate service. If you are not using Node.js then this is the only option available to you.
|
||||
|
||||
## As an [NPM library](./npm-library.md)
|
||||
|
||||
This is available if you are already developing your application using Node.js.
|
||||
|
||||
The advantage of embedding Jackson as an npm library is that you do not have to manage operations of a separate service. The disadvantage is that you do not readily get our UI tooling (like the Admin Portal) with this method.
|
@ -0,0 +1,442 @@
|
||||
# NPM Library
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
SAML Jackson is available as an [npm package](https://www.npmjs.com/package/@boxyhq/saml-jackson) that can be integrated into any **Node.js** based web application framework.
|
||||
|
||||
Install the SDK using the command below.
|
||||
|
||||
```bash
|
||||
npm install @boxyhq/saml-jackson
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration Options
|
||||
|
||||
Please note that the initialization of `@boxyhq/saml-jackson` is async, you cannot run it at the top level.
|
||||
|
||||
```js
|
||||
import jackson, {
|
||||
type IConnectionAPIController,
|
||||
type IOAuthController,
|
||||
} from '@boxyhq/saml-jackson';
|
||||
|
||||
let oauth: IOAuthController;
|
||||
let connection: IConnectionAPIController;
|
||||
|
||||
(async function init() {
|
||||
const jackson = await require('@boxyhq/saml-jackson').controllers({
|
||||
externalUrl: 'https://your-app.com',
|
||||
samlAudience: 'https://saml.boxyhq.com',
|
||||
oidcPath: '/api/oauth/oidc',
|
||||
samlPath: '/api/oauth/saml',
|
||||
db: {
|
||||
engine: 'sql',
|
||||
type: 'postgres',
|
||||
url: 'postgres://postgres:postgres@localhost:5432/postgres',
|
||||
},
|
||||
});
|
||||
|
||||
oauth = jackson.oauthController;
|
||||
connection = jackson.connectionAPIController;
|
||||
})();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Single Sign-On Connections
|
||||
|
||||
### Create SAML Connection
|
||||
|
||||
Create a new SAML Single Sign-On connection.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Request" default>
|
||||
|
||||
```js
|
||||
await connection.createSAMLConnection({
|
||||
tenant: 'boxyhq',
|
||||
product: 'your-app',
|
||||
rawMetadata: '<raw-saml-metadata>', // Visit https://mocksaml.com to download Metadata
|
||||
redirectUrl: ['https://your-app.com/*'],
|
||||
defaultRedirectUrl: 'https://your-app.com/sso/callback',
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="02" label="Response">
|
||||
|
||||
```json
|
||||
{
|
||||
"defaultRedirectUrl": "https://your-app.com/sso/callback",
|
||||
"redirectUrl": ["https://your-app.com/*"],
|
||||
"tenant": "boxyhq",
|
||||
"product": "your-app",
|
||||
"clientID": "f7c909a5c72a5535847acf32558b2429a5172dd6",
|
||||
"clientSecret": "cc6ba07bc42c2f449c9b0a3cc41c256dea08f705e1b44fdc",
|
||||
"forceAuthn": false,
|
||||
"idpMetadata": {
|
||||
"sso": {
|
||||
"postUrl": "https://mocksaml.com/api/saml/sso",
|
||||
"redirectUrl": "https://mocksaml.com/api/saml/sso"
|
||||
},
|
||||
"slo": {},
|
||||
"entityID": "https://saml.example.com/entityid",
|
||||
"thumbprint": "d797f3829882233d3f01e49643f6a1195f242c94",
|
||||
"validTo": "Jul 1 21:46:38 3021 GMT",
|
||||
"loginType": "idp",
|
||||
"provider": "saml.example.com"
|
||||
},
|
||||
"certs": {
|
||||
"publicKey": "-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----\r\n",
|
||||
"privateKey": "-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----\r\n"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Update SAML Connection
|
||||
|
||||
Update a SAML Single Sign-On connection.
|
||||
|
||||
```js
|
||||
await connection.updateSAMLConnection({
|
||||
tenant: 'boxyhq',
|
||||
product: 'your-app',
|
||||
rawMetadata: '<raw-saml-metadata>',
|
||||
redirectUrl: ['https://your-app.com/*'],
|
||||
defaultRedirectUrl: 'https://your-app.com/sso/callback-updated',
|
||||
clientID: '<clientID of the SAML SSO Connection>',
|
||||
clientSecret: '<clientSecret of the SAML SSO Connection>',
|
||||
});
|
||||
```
|
||||
|
||||
### Create OIDC Connection
|
||||
|
||||
Create a new OIDC Single Sign-On connection.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Request" default>
|
||||
|
||||
```js
|
||||
await connection.createOIDCConnection({
|
||||
tenant: 'boxyhq',
|
||||
product: 'your-app',
|
||||
redirectUrl: ['https://your-app.com/*'],
|
||||
defaultRedirectUrl: 'https://your-app.com/sso/callback',
|
||||
oidcDiscoveryUrl:
|
||||
'https://accounts.google.com/.well-known/openid-configuration',
|
||||
oidcClientId: '<OpenID Client ID>',
|
||||
oidcClientSecret: '<OpenID Client Secret>',
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="02" label="Response">
|
||||
|
||||
```json
|
||||
{
|
||||
"defaultRedirectUrl": "https://your-app.com/sso/callback",
|
||||
"redirectUrl": ["https://your-app.com/*"],
|
||||
"tenant": "boxyhq",
|
||||
"product": "your-app",
|
||||
"clientID": "749f95c4bd02b4adb6c0633249e70d5ad45b75e2",
|
||||
"clientSecret": "2d730ac71c74e7d49dccf362c9a61005b6246cc65d6d0fa4",
|
||||
"oidcProvider": {
|
||||
"discoveryUrl": "https://accounts.google.com/.well-known/openid-configuration",
|
||||
"clientId": "<OpenID Client ID>",
|
||||
"clientSecret": "<OpenID Client Secret>",
|
||||
"provider": "accounts.google.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Update OIDC Connection
|
||||
|
||||
Update an OIDC Single Sign-On connection.
|
||||
|
||||
```js
|
||||
await connection.updateOIDCConnection({
|
||||
tenant: 'boxyhq',
|
||||
product: 'your-app',
|
||||
redirectUrl: ['https://your-app.com/*'],
|
||||
defaultRedirectUrl: 'https://your-app.com/sso/callback',
|
||||
oidcDiscoveryUrl:
|
||||
'https://accounts.google.com/.well-known/openid-configuration',
|
||||
oidcClientId: '<OpenID Client ID>',
|
||||
oidcClientSecret: '<OpenID Client Secret>',
|
||||
clientID: '<clientID of the OIDC SSO Connection>',
|
||||
clientSecret: '<clientSecret of the OIDC SSO Connection>',
|
||||
});
|
||||
```
|
||||
|
||||
### Get SAML/OIDC Connections
|
||||
|
||||
Get the details of an existing SAML or OIDC Single Sign-On connection.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Request" default>
|
||||
|
||||
```js
|
||||
// Using tenant and product
|
||||
await connection.getConnections({
|
||||
tenant: 'boxyhq',
|
||||
product: 'your-app',
|
||||
});
|
||||
|
||||
// Using the client ID
|
||||
await connection.getConnections({
|
||||
clientID: '<clientID of the SSO Connection to be retrieved>.',
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="02" label="Response">
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"defaultRedirectUrl": "https://your-app.com/sso/callback",
|
||||
"redirectUrl": ["https://your-app.com/*"],
|
||||
"tenant": "boxyhq",
|
||||
"product": "your-app",
|
||||
"clientID": "...",
|
||||
"clientSecret": "...",
|
||||
"forceAuthn": false,
|
||||
"idpMetadata": {
|
||||
"sso": {
|
||||
"postUrl": "https://mocksaml.com/api/saml/sso",
|
||||
"redirectUrl": "https://mocksaml.com/api/saml/sso"
|
||||
},
|
||||
"slo": {},
|
||||
"entityID": "https://saml.example.com/entityid",
|
||||
"thumbprint": "d797f3829882233d3f01e49643f6a1195f242c94",
|
||||
"validTo": "Jul 1 21:46:38 3021 GMT",
|
||||
"loginType": "idp",
|
||||
"provider": "saml.example.com"
|
||||
},
|
||||
"certs": {
|
||||
"publicKey": "-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----\r\n",
|
||||
"privateKey": "-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----\r\n"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Delete SAML/OIDC Connection
|
||||
|
||||
Update a SAML or OIDC Single Sign-On connection.
|
||||
|
||||
```js
|
||||
// Using tenant and product
|
||||
await connection.deleteConnections({
|
||||
tenant: 'boxyhq',
|
||||
product: 'your-app',
|
||||
});
|
||||
|
||||
// Using client ID and client secret
|
||||
await connection.deleteConnections({
|
||||
clientID: '<clientID of the SSO Connection>',
|
||||
clientSecret: '<clientSecret of the SSO Connection>',
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Single Sign-On Authentication
|
||||
|
||||
### Handle OAuth 2.0 (or OIDC) Authorization request
|
||||
|
||||
To initiate the flow, the application must trigger an OAuth 2.0 (or OIDC) redirect to the authorization endpoint of your app. You'll use the `authorize` method within the authorization handler.
|
||||
|
||||
`authorize` will resolve the SSO URL (`redirect_url`) based on the connection configured for the tenant/product. The app needs to redirect the user to this URL. Keep in mind that the SSO URL structure is different based on the type of SSO Connection. For a SAML Connection, this will contain the `SAMLRequest` whereas for an OIDC Connection the SSO URL will be the Authorization endpoint with the OIDC request params (scope, response_type, etc.) attached.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Request" default>
|
||||
|
||||
```ts
|
||||
await oauth.authorize({
|
||||
tenant: 'boxyhq',
|
||||
product: 'your-app',
|
||||
redirect_uri:
|
||||
'<app redirect URI to which Jackson sents back the authorization code after authentication>',
|
||||
state:
|
||||
'<opaque value from the app which will be returned back from Jackson, this is need to prevent CSRF attacks>',
|
||||
response_type: 'code',
|
||||
code_challenge:
|
||||
'<transformed value of code_verifier used to prevent interception of authorization_code in PKCE flow>',
|
||||
code_challenge_method:
|
||||
'<transformation method applied on code_verifier to generate code_challenge>',
|
||||
scope:
|
||||
'<can contain space separated values such as openid or even encoded tenant/product>',
|
||||
nonce:
|
||||
'<string value used to associate a client session with an ID Token in openid flow, and to mitigate replay attacks>',
|
||||
idp_hint:
|
||||
'<this will contain the clientID of the SSO connection that the user selects in the case of multiple ones configured for a tenant/product>',
|
||||
prompt: '<pass "login" to force authentication at the SAML IdP>',
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="02" label="Response">
|
||||
|
||||
```json
|
||||
{
|
||||
"redirect_url": "https://mocksaml.com/api/saml/sso?RelayState=boxyhq_jackson_...&SAMLRequest=nVbZkqs4En33V1T4...",
|
||||
"authorize_form": ""
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Handle IdP Response
|
||||
|
||||
The response is sent back to your app after authentication at IdP. After the handling of this response, the profile of the authenticated user is extracted and stored against a short-lived code that is then sent back to the app. To handle the response use the appropriate method as detailed below:
|
||||
|
||||
#### SAML Response
|
||||
|
||||
Handle the response from the SAML Identity Provider. After successful authentication, IdP sends back (via browser POST) the `SAMLResponse` and `RelayState` to the Assertion Consumer Service (ACS) URL (`samlPath`) of the app. You'll use the `samlResponse` method within your ACS endpoint. This will parse and validate the SAML Response after which the user profile is extracted.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Request" default>
|
||||
|
||||
```js
|
||||
await oauth.samlResponse({
|
||||
SAMLResponse: '<SAML Response from the SAML IdP>',
|
||||
RelayState: '<Relaystate from the original SAML request to the IdP>',
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="02" label="Response">
|
||||
|
||||
```json
|
||||
{
|
||||
"redirect_url": "https://your-app.com/sso/callback?code=5db7257fde94e062f6243572e31818d6e64c3097&state=c38ee339-6b82-43d3-838f-4036820acce9"
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### OIDC Response
|
||||
|
||||
Handle the response from the OIDC Identity Provider. After successful authentication, IdP sends back (via browser redirect) the `code` and `state` to the redirect URL (`oidcPath`) that handles the OIDC response. You'll use the `oidcAuthzResponse` method within your `oidcPath` handler. This will exchange the `code` for tokenSet (id_token and access_token) from the OIDC Provider. The "userinfo" endpoint of the OIDC Provider also gets invoked. Both the `id_token` claims and `userinfo` response are used to form the user profile.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Request" default>
|
||||
|
||||
```js
|
||||
await oauth.oidcAuthzResponse({
|
||||
code: '<code received from OIDC IdP after authentication>',
|
||||
state: '<state from the original OIDC request to the IdP>',
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="02" label="Response">
|
||||
|
||||
```json
|
||||
{
|
||||
"redirect_url": "https://your-app.com/sso/callback?code=5db7257fde94e062f6243572e31818d6e64c3097&state=c38ee339-6b82-43d3-838f-4036820acce9"
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Request Access Token
|
||||
|
||||
Requests an `access_token` by passing the authorization `code` from the previous step along with other authentication details.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Request" default>
|
||||
|
||||
```js
|
||||
const tenant = 'boxyhq';
|
||||
const product = 'your-app';
|
||||
|
||||
await oauth.token({
|
||||
code: '<Authorization code received from Jackson at redirect_url after login at IdP>',
|
||||
redirect_uri:
|
||||
'<redirect_uri used in original authorization request to Jackson>',
|
||||
client_id: `tenant=${tenant}&product=${product}`,
|
||||
client_secret: 'dummy',
|
||||
grant_type: 'authorization_code',
|
||||
});
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="02" label="Response">
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": "6b81f03b60c34e46e740d96c7e6242923736a2d1",
|
||||
"token_type": "bearer",
|
||||
"expires_in": 300
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Fetch User Profile
|
||||
|
||||
Once the `access_token` has been fetched, you can use it to retrieve the user profile from the Identity Provider.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="01" label="Request" default>
|
||||
|
||||
```js
|
||||
const accessToken = '<Access token from code exchange step above>';
|
||||
|
||||
await oauth.userInfo(accessToken);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="02" label="Response">
|
||||
|
||||
```json
|
||||
{
|
||||
"raw": {
|
||||
"id": "1dda9fb491dc01bd24d2423ba2f22ae561f56ddf2376b29a11c80281d21201f9",
|
||||
"email": "samuel@example.com",
|
||||
"firstName": "Samuel",
|
||||
"lastName": "Jackson",
|
||||
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "samuel@example.com"
|
||||
},
|
||||
"id": "1dda9fb491dc01bd24d2423ba2f22ae561f56ddf2376b29a11c80281d21201f9",
|
||||
"email": "samuel@example.com",
|
||||
"firstName": "Samuel",
|
||||
"lastName": "Jackson",
|
||||
"requested": {
|
||||
"client_id": "f7c909a5c72a5535847acf32558b2429a5172dd6",
|
||||
"state": "c38ee339-6b82-43d3-838f-4036820acce9",
|
||||
"redirect_uri": "https://your-app.com/sso/callback",
|
||||
"tenant": "boxyhq",
|
||||
"product": "your-app",
|
||||
"scope": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
@ -0,0 +1,50 @@
|
||||
# Pre-loaded SSO Connections
|
||||
|
||||
#### SAML
|
||||
|
||||
If PRE_LOADED_CONNECTION is set then it should point to a directory with the following structure (example below):-
|
||||
|
||||
```bash
|
||||
boxyhq.js
|
||||
boxyhq.xml
|
||||
anothertenant.js
|
||||
anothertenant.xml
|
||||
```
|
||||
|
||||
The JS file has the following structure:-
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
defaultRedirectUrl: 'http://localhost:3366/login/saml',
|
||||
redirectUrl: '["http://localhost:3366/*"]',
|
||||
tenant: 'boxyhq.com',
|
||||
product: 'demo',
|
||||
name: 'testConnection',
|
||||
description: 'Just a test connection',
|
||||
};
|
||||
```
|
||||
|
||||
The XML file (which should have the same name as the .js file) is the raw XML metadata file you receive from your Identity Provider. Please ensure it is saved in the `utf-8` encoding.
|
||||
|
||||
The config and XML above correspond to the [Add connection API - SAML tab](../sso-flow/index.md#21-add-connection).
|
||||
|
||||
#### OIDC
|
||||
|
||||
For a connection backed by OpenID IdP create the \*.js file at PRE_LOADED_CONNECTION as shown below:-
|
||||
|
||||
See [Add connection API - OIDC tab](../sso-flow/index.md#21-add-connection)
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
defaultRedirectUrl: 'http://localhost:3366/sso/oauth/oidc',
|
||||
redirectUrl: '["http://localhost:3366"]',
|
||||
tenant: 'oidc.example.com',
|
||||
product: 'crm',
|
||||
name: 'OIDC connection for oidc.example.com',
|
||||
description: 'OIDC connection for oidc.example.com',
|
||||
oidcDiscoveryUrl:
|
||||
'https://accounts.google.com/.well-known/openid-configuration',
|
||||
oidcClientId: '<ClientId from the OpenID IdP>',
|
||||
oidcClientSecret: '<ClientSecret from the OpenID IdP>',
|
||||
};
|
||||
```
|
@ -0,0 +1,144 @@
|
||||
# Service
|
||||
|
||||
## Health Check
|
||||
|
||||
The service offers a readiness and health check endpoint that can be configured in orchestration tools like Docker Compose and Kubernetes.
|
||||
|
||||
The `/api/health` GET endpoint returns a 200 when the service ready and healthy or a 5xx (typically 503) error if unhealthy. The response contains the current version of Jackson. For example: `{"version":"1.0.0"}`.
|
||||
|
||||
## With Docker
|
||||
|
||||
The docker container can be found at [boxyhq/jackson](https://hub.docker.com/r/boxyhq/jackson/tags). It is preferable to use a specific version instead of the `latest` tag.
|
||||
|
||||
Replace the values for `DB_URL`, `JACKSON_API_KEYS`, `NEXTAUTH_SECRET` and `NEXTAUTH_ADMIN_CREDENTIALS` with your own values before running docker run command.
|
||||
|
||||
```bash
|
||||
docker run \
|
||||
-p 5225:5225 \
|
||||
-e DB_ENGINE="sql" \
|
||||
-e DB_TYPE="postgres" \
|
||||
-e DB_URL="postgres://postgres:postgres@postgres:5432/postgres" \
|
||||
-e JACKSON_API_KEYS="secret" \
|
||||
-e NEXTAUTH_URL="http://localhost:5225" \
|
||||
-e EXTERNAL_URL="http://localhost:5225" \
|
||||
-e NEXTAUTH_SECRET="super-secret" \
|
||||
-e NEXTAUTH_ADMIN_CREDENTIALS="admin@company.com:secretpassword" \
|
||||
-d boxyhq/jackson
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
```bash
|
||||
docker run \
|
||||
-p 5225:5225 \
|
||||
-e DB_ENGINE="mongo" \
|
||||
-e DB_URL="mongodb://localhost:27017/jackson" \
|
||||
-e JACKSON_API_KEYS="secret" \
|
||||
-e NEXTAUTH_URL="http://localhost:5225" \
|
||||
-e EXTERNAL_URL="http://localhost:5225" \
|
||||
-e NEXTAUTH_SECRET="super-secret" \
|
||||
-e NEXTAUTH_ADMIN_CREDENTIALS="admin@company.com:secretpassword" \
|
||||
-d boxyhq/jackson
|
||||
```
|
||||
|
||||
See the complete list of [Environment Variables](./env-variables.md)
|
||||
|
||||
Kubernetes and docker-compose deployment files will be coming soon.
|
||||
|
||||
## Without Docker
|
||||
|
||||
Please follow the below instructions.
|
||||
|
||||
### Clone the repository
|
||||
|
||||
You can clone the source from the [Jackson GitHub repo](https://github.com/boxyhq/jackson/tree/release)
|
||||
|
||||
```bash
|
||||
git clone https://github.com/boxyhq/jackson
|
||||
```
|
||||
|
||||
```bash
|
||||
cd jackson
|
||||
```
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### Add environment variables
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Update `.env` with your values. See the complete list of [Environment Variables](./env-variables.md)
|
||||
|
||||
### Build and run
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
```bash
|
||||
npm run start
|
||||
```
|
||||
|
||||
## Test the service is running
|
||||
|
||||
Open a browser and visit [http://localhost:5225](http://localhost:5225).
|
||||
|
||||
If you see a page asking you to sign in, congrats 🎉 you are seeing the [Admin Portal](../../admin-portal/overview).
|
||||
|
||||
## Database
|
||||
|
||||
Jackson currently supports the following databases.
|
||||
|
||||
- Postgres
|
||||
- MySQL
|
||||
- Microsoft SQL Server
|
||||
- MariaDB
|
||||
- MongoDB
|
||||
- Redis
|
||||
- [PlanetScale](https://planetscale.com/) (MySQL compatible)
|
||||
- [Neon](https://neon.tech) (Serverless Postgres)
|
||||
- Amazon DynamoDB
|
||||
|
||||
### PlanetScale
|
||||
|
||||
To connect PlanetScale database with Jackson, follow the below steps:
|
||||
|
||||
1. Create a new database on PlanetScale
|
||||
2. Get your database [connection URL from the PlanetScale](https://planetscale.com/docs/tutorials/deploy-to-netlify#get-your-connection-string-from-planetscale)
|
||||
3. Set the following environment variables
|
||||
|
||||
- `DB_ENGINE=planetscale`
|
||||
- `DB_TYPE=mysql`
|
||||
- `DB_SSL=true`
|
||||
- `DATABASE_URL=<PlanetScale connection URL>`
|
||||
|
||||
4. Run the database migration to create the tables required by SAML Jackson
|
||||
|
||||
```bash
|
||||
cd npm && PLANETSCALE_URL=<PlanetScale connection URL> npm run db:migration:run:planetscale
|
||||
```
|
||||
|
||||
Make sure you have `?ssl={"rejectUnauthorized":true}` at the end of the PlanetScale connection URL.
|
||||
|
||||
Now you are ready to start the service.
|
||||
|
||||
## SAML Tracer
|
||||
|
||||
Each error event in the SAML request/ response phase is captured to aid in troubleshooting the SAML setup. The record or trace contains context related to the flow, like tenant, product, etc. The Admin Portal will have a tab under Enterprise SSO -> SAML Tracer showing a paginated list of traces over time. Developers can inspect a trace and will be able to ascertain the real reason for the failure.
|
||||
|
||||
## Deployment Guides (Coming soon)
|
||||
|
||||
- Heroku
|
||||
- DigitalOcean
|
||||
- Vercel
|
||||
- Docker
|
||||
- Kubernetes
|
||||
- AWS
|
||||
- GCP
|
||||
- Azure
|
@ -0,0 +1,117 @@
|
||||
---
|
||||
title: Enterprise SSO Webhook Events
|
||||
sidebar_label: Events
|
||||
---
|
||||
|
||||
# Webhook Events
|
||||
|
||||
SAML Jackson uses webhooks to notify your application any time changes are made to the connections. We'll notify you of the following 4 events for each connection.
|
||||
|
||||
## Events
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
sso.created - New connection has been created.
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "sso.created",
|
||||
"tenant": "boxyhq",
|
||||
"product": "demo",
|
||||
"data": {
|
||||
"name": "SSO Connection",
|
||||
"description": "SSO Connection for BoxyHQ",
|
||||
"clientID": "326991705d478f0178fc2b49e35cd166dc771061",
|
||||
"clientSecret": "15b2db91b2ba4c848b68148f108035e7138d69104d99de89",
|
||||
"provider": "saml.example.com",
|
||||
"friendlyProviderName": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
sso.deactivated - A connection has been deactivated.
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "sso.deactivated",
|
||||
"tenant": "boxyhq",
|
||||
"product": "demo",
|
||||
"data": {
|
||||
"name": "SSO Connection",
|
||||
"description": "SSO Connection for BoxyHQ",
|
||||
"clientID": "326991705d478f0178fc2b49e35cd166dc771061",
|
||||
"clientSecret": "15b2db91b2ba4c848b68148f108035e7138d69104d99de89",
|
||||
"provider": "saml.example.com",
|
||||
"friendlyProviderName": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
sso.activated - A connection has been activated.
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "sso.activated",
|
||||
"tenant": "boxyhq",
|
||||
"product": "demo",
|
||||
"data": {
|
||||
"name": "SSO Connection",
|
||||
"description": "SSO Connection for BoxyHQ",
|
||||
"clientID": "326991705d478f0178fc2b49e35cd166dc771061",
|
||||
"clientSecret": "15b2db91b2ba4c848b68148f108035e7138d69104d99de89",
|
||||
"provider": "saml.example.com",
|
||||
"friendlyProviderName": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
sso.deleted - A connection has been deleted.
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
```json
|
||||
{
|
||||
"event": "sso.deleted",
|
||||
"tenant": "boxyhq",
|
||||
"product": "demo",
|
||||
"data": {
|
||||
"name": "SSO Connection",
|
||||
"description": "SSO Connection for BoxyHQ",
|
||||
"clientID": "326991705d478f0178fc2b49e35cd166dc771061",
|
||||
"clientSecret": "15b2db91b2ba4c848b68148f108035e7138d69104d99de89",
|
||||
"provider": "saml.example.com",
|
||||
"friendlyProviderName": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
## Configure Webhook
|
||||
|
||||
To configure the webhook, you have to set the following environment variables.
|
||||
|
||||
- `WEBHOOK_URL` - The URL to which the webhook events will be sent.
|
||||
- `WEBHOOK_SECRET` - The secret key used to sign the webhook events.
|
@ -0,0 +1,27 @@
|
||||
---
|
||||
title: Examples & Resources (Enterprise SSO)
|
||||
sidebar_label: Examples & Resources
|
||||
description: Examples & Resources for our Enterprise SSO product
|
||||
---
|
||||
|
||||
# Examples & Resources (Enterprise SSO)
|
||||
|
||||
## Examples
|
||||
|
||||
- [Jackson with Next.js and NextAuth.js](https://github.com/boxyhq/jackson-examples/tree/main/apps/next-auth)
|
||||
- [Jackson with Remix and remix-auth](https://github.com/boxyhq/jackson-remix-auth)
|
||||
- [Jackson with React and client-side OAuth](https://github.com/boxyhq/jackson-examples/tree/main/apps/react)
|
||||
- [Jackson with Express.js](https://github.com/boxyhq/jackson-examples/tree/main/apps/express)
|
||||
- [Jackson with Supertokens and Express.js](https://github.com/boxyhq/jackson-supertokens-express)
|
||||
- [Jackson with Express.js and Auth0](https://github.com/boxyhq/express-jackson-auth0-demo)
|
||||
|
||||
## Resources
|
||||
|
||||
- [Mock SAML hosted service](https://mocksaml.com)
|
||||
- [Mock SAML](https://github.com/boxyhq/mock-saml)
|
||||
- [NextAuth.js Provider](https://next-auth.js.org/providers/boxyhq-saml)
|
||||
- [Remix Auth Strategy](https://github.com/boxyhq/remix-auth-saml)
|
||||
|
||||
## Third-party examples
|
||||
|
||||
- [Jackson with Next.js and Supertokens](https://github.com/nadilas/jackson-next-supertokens)
|
@ -0,0 +1,57 @@
|
||||
# Local Development
|
||||
|
||||
This guide will help you to setup and run SAML Jackson in development mode.
|
||||
|
||||
## Clone the repo
|
||||
|
||||
```bash
|
||||
git clone https://github.com/boxyhq/jackson.git
|
||||
|
||||
cd jackson
|
||||
```
|
||||
|
||||
## Install dependencies
|
||||
|
||||
Run the following command to install the Node dependencies.
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
## Setup environment variables
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Please refer to [environment variables](./deploy/env-variables.md) to read on setting environment variables.
|
||||
|
||||
## Setup the database
|
||||
|
||||
Run the following command to create database instances for the local development. Make sure you have Docker installed on your machine.
|
||||
|
||||
```bash
|
||||
npm run dev-dbs
|
||||
```
|
||||
|
||||
## Start the development server
|
||||
|
||||
Start the development server by running the following command.
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Testing Jackson in your local environment
|
||||
|
||||
The Jackson service can be accessed locally using the following URL
|
||||
|
||||
```bash
|
||||
http://localhost:5225
|
||||
```
|
||||
|
||||
You can visit the following URL to see if the Jackson was started successfully!
|
||||
|
||||
```bash
|
||||
http://localhost:5225/api/hello
|
||||
```
|
@ -0,0 +1,16 @@
|
||||
# Observability
|
||||
|
||||
Jackson provides first-class observability on the back of OpenTelemetry. Currently we support the following metrics. Traces and logs are coming soon.
|
||||
|
||||
Please check the [Environment Variables](./deploy/env-variables.md#opentelemetry-configuration) to configure to enable this feature.
|
||||
|
||||
## Metrics
|
||||
|
||||
| Name | Description | Type |
|
||||
| --------------------------- | ---------------------------------------- | ----- |
|
||||
| `jackson.connection.create` | Number of SSO Connection create requests | Count |
|
||||
| `jackson.connection.get` | Number of SSO Connection get requests | Count |
|
||||
| `jackson.connection.delete` | Number of SSO Connection delete requests | Count |
|
||||
| `jackson.oauth.authorize` | Number of oauth authorize requests | Count |
|
||||
| `jackson.oauth.token` | Number of oauth token requests | Count |
|
||||
| `jackson.oauth.userinfo` | Number of oauth user info requests | Count |
|
@ -0,0 +1,25 @@
|
||||
---
|
||||
title: SAML Federation
|
||||
sidebar_label: SAML Federation
|
||||
---
|
||||
|
||||
# SAML Federation
|
||||
|
||||
SAML Federation is an enterprise feature and you need to have an enterprise license to use this feature.
|
||||
|
||||
This feature allows you to federate multiple Identity Providers (IdPs) without needing any additional plugins or code changes. Extremely useful in cases where the SAML support is restricted to a single provider and you need to support multiple IdPs. Contact us to find out more.
|
||||
|
||||
## SAML Federation Flow
|
||||
|
||||
Here is how the SAML Federation flow works if you are using Jackson as a SAML IdP and want to federate with another identity provider (IdP) (Eg: Okta):
|
||||
|
||||
- The user accesses the Service Provider's (SP) login page
|
||||
- The user clicks on the "Login with SAML" button
|
||||
- The SP sends SAML Request to Jackson's SSO endpoint
|
||||
- Jackson displays the list of IdP available for the user to choose from (if there is more than one IdP) based on the requested tenant and product combination
|
||||
- Jackson redirects the user to the chosen IdP for authentication
|
||||
- After successful authentication, IdP sends (POST) SAML Response to Jackson's ACS endpoint
|
||||
- Jackson process SAML Response from the IdP and create a new SAML Response to send (POST) back to the SP's ACS endpoint
|
||||
- SP process SAML Response from Jackson and create a new session for the user (Depending on the SP's implementation)
|
||||
|
||||
Visit [Create SAML Federation App](/docs/admin-portal/enterprise-sso#saml-federation) to learn how to create and configure a SAML Federation App.
|
@ -0,0 +1,25 @@
|
||||
# Software Bill Of Materials (SBOM) Reports
|
||||
|
||||
[SBOM](https://en.wikipedia.org/wiki/Software_bill_of_materials) is a list of components in a piece of software. It is like a list of ingredients of a product and is quickly becoming a standard for software supply chain risk management. The ecosystem is growing with tools that help you verify, scan and monitor all your dependencies.
|
||||
|
||||
## Report Standards
|
||||
|
||||
SBOM reports primarily use [SPDX](https://en.wikipedia.org/wiki/Software_Package_Data_Exchange) & [CycloneDX](https://cyclonedx.org/) standards.
|
||||
|
||||
## Reports
|
||||
|
||||
**Note:** This is supported for all versions >=0.3.8
|
||||
|
||||
You can find the SBOM reports as artifacts in our container registry at the locations below. They are updated every time there is change in the codebase and tagged by the exact version we release.
|
||||
|
||||
| Location | Files | Context |
|
||||
| ----------------------------------------------- | ----------------------------- | ------------------------------------- |
|
||||
| `ghcr.io/boxyhq/jackson/sbom:service-<version>` | `sbom.spdx`, `sbom.cyclonedx` | SAML Jackson service |
|
||||
| `ghcr.io/boxyhq/jackson/sbom:npm-<version>` | `sbom.spdx`, `sbom.cyclonedx` | NPM package |
|
||||
| `ghcr.io/boxyhq/jackson/sbom:docker-<version>` | `sbom.spdx`, `sbom.cyclonedx` | Docker Image for SAML Jackson service |
|
||||
|
||||
You can use [oras](https://oras.land/docs/category/cli) (or a similar OCI artifacts tool) to retrieve these files.
|
||||
|
||||
```bash
|
||||
oras pull ghcr.io/boxyhq/jackson/sbom:service-<version>
|
||||
```
|
@ -0,0 +1,17 @@
|
||||
# Security
|
||||
|
||||
In general most OAuth 2.0 security guidelines apply to Jackson as well but there are a few minor differences.
|
||||
|
||||
## Tenancy
|
||||
|
||||
OAuth 2.0 is typically a single instance and all users can login using the same instance. However SAML is based on an specific instance that your customers have to configure with their Identity Provider. This means that access to the SAML instance is limited to only those that have been provisioned for it, adding another layer of security to the login flow.
|
||||
|
||||
## Client Secret
|
||||
|
||||
The Config API returns a `client_id` and `client_secret` that you can save for each customer and use when initiating the OAuth 2.0 flow. However for convenience we also let you use a `tenant` and `product` instead since this doesn't require you to store any additional data. When using this we recommend you use the [CLIENT_SECRET_VERIFIER](./deploy/env-variables.md#client_secret_verifier) configuration and not use the default `dummy` value. The `client_secret` cannot really be misused because as you will see in the next section the tokens are short lived but it is a good idea to set the `client_secret` to something that is really a secret.
|
||||
|
||||
For client-side logins we highly recommend you use the PKCE flow which is supported by Jackson. This ensures a secure login without revealing the `client_secret` on the client-side.
|
||||
|
||||
## Tokens
|
||||
|
||||
The tokens generated by Jackson are short lived (default is 5 minutes) and hence there is no risk of it being misused even if the `client_secret` is known. Your SAML provider ensures that there can be no unauthorized.
|
@ -0,0 +1,29 @@
|
||||
---
|
||||
title: Example flow
|
||||
sidebar_label: Example flow
|
||||
---
|
||||
|
||||
## Scenario
|
||||
|
||||
Let's say you have a customer `acme.com` who is using two of your SaaS offerings. For now let's call them:
|
||||
|
||||
- `CRM (Customer Relationship Management)` - Should integrate with the customer (of acme.com) facing SAML Identity Provider (Azure AD)
|
||||
- `HRM (Human Resource Management)` - Should integrate with the Google workspace account of `acme.com` employees.
|
||||
|
||||
Let's see how SSO works in this case.
|
||||
|
||||
## Configure the SSO Connection
|
||||
|
||||
First as the application developer, you'll need to [add](./index.md#21-add-connection) the SSO connections for CRM and HRM. This will be saved (marked as SAML Metadata and OIDC Metadata in the below diagram) within Jackson and later used to orchestrate the IdP login.
|
||||
|
||||
## Login flow
|
||||
|
||||
Jackson uses the Authorization Code flow as outlined by the numbered steps below.
|
||||
|
||||
1. The Client (Browser app) initiates the login by redirecting to Jackson [`authorize`](./index.md#31-authorize) endpoint. Jackson will parse the tenant/product in the request and use it to redirect the user to the configured IdP.
|
||||
2. Step 2 varies based on the Identity Provider type. For SAML IdP, Jackson would construct the SAML request, sign it and send it to IdP. The IdP validates the request and redirects the user to the login screen. For OIDC IdP, Jackson constructs an OpenID Connect request and redirects the user to the OIDC Provider authorization endpoint.
|
||||
3. Once the user is logged in successfully, the IdP redirects back to Jackson. For SAML, the response contains the user profile. In the case of OIDC, the response contains the authorization code that is used by Jackson to obtain token and userprofile from the OIDC IdP. Jackson generates a short lived code and stores the user profile against it.
|
||||
4. The authorization code generated in the previous step is sent to the client app.
|
||||
5. The client [`exchanges`](./index.md#32-code-exchange) the code for token and uses it to query the [`userInfo`](./index.md#33-profile-request) endpoint of Jackson to get the complete user profile.
|
||||
|
||||

|
@ -0,0 +1,333 @@
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
# Single Sign-On (SSO)
|
||||
|
||||
Jackson takes a multi-tenanted approach to implementing SSO, abstracting away all the complexities of the underlying SAML/OIDC protocol. What this means is you can enable SSO for all (your) customers across products from a single instance of jackson, and works with both SAML and OIDC Identity Provider(IdP)s.
|
||||
|
||||
**Note:** All the APIs below support both `application/x-www-form-urlencoded` and `application/json` content types. Examples below use `application/x-www-form-urlencoded`.
|
||||
|
||||
**Note:** OAuth 2.0 protocol uses underscore casing for the parameters, we use camel casing for all our APIs. For example it's `client_id` in the OAuth 2.0 flow and `clientID` in our APIs.
|
||||
|
||||
## 1. Setting up SSO Provider
|
||||
|
||||
Please follow the instructions [here](../sso-providers) to guide your customers in setting up SAML/OIDC correctly for your product(s). You should create a copy of the doc and modify it with your custom settings, we have used the values that work for our demo apps.
|
||||
|
||||
## 2. SSO Connection API
|
||||
|
||||
You will need to provide a place in the UI for your customers (The account settings page is usually a good place for this) to configure this and then call the APIs below.
|
||||
|
||||
### 2.1 Add connection
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="saml" label="SAML" default>
|
||||
|
||||
Once your customer has set up the SAML app on their Identity Provider, the Identity Provider will generate an IdP or SP metadata file. Some Identity Providers only generate an IdP metadata file but it usually works for the SP login flow as well. It is an XML file that contains various attributes Jackson needs to validate incoming SAML login requests. This step is the equivalent of setting an OAuth 2.0 app and generating a client ID and client secret that will be used in the login flow.
|
||||
|
||||
The following API call sets up the connection in Jackson:
|
||||
|
||||
```bash
|
||||
curl --location --request POST 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'encodedRawMetadata=Base64(<IdP/SP metadata XML>)' \
|
||||
--data-urlencode 'defaultRedirectUrl=http://localhost:3366/login/saml' \
|
||||
--data-urlencode 'redirectUrl=http://localhost:3366/*' \
|
||||
--data-urlencode 'redirectUrl=http://localhost:3000/*' \
|
||||
--data-urlencode 'tenant=boxyhq.com' \
|
||||
--data-urlencode 'product=demo' \
|
||||
--data-urlencode 'name=demo-connection' \
|
||||
--data-urlencode 'description=Demo SAML connection'
|
||||
```
|
||||
|
||||
- `metadataUrl`: URL containing the SAML metadata contents. Either this or `encodedRawMetadata` needs to be specified
|
||||
- `encodedRawMetadata`: Base64 encoding of the XML metadata your customer gets from their Identity Provider. Either this or `metadataUrl` needs to be specified
|
||||
- `defaultRedirectUrl`: The redirect URL to use in the IdP login flow. Jackson will call this URL after completing an IdP login flow
|
||||
- `redirectUrl`: Allowed redirect URL. Repeat this field multiple times to allow multiple redirect URLs. Jackson will disallow any redirects not on this list (or not the default URL above).
|
||||
- `tenant`: Jackson supports a multi-tenant architecture, this is a unique identifier you set from your side that relates back to your customer's tenant. This is normally an email, domain, an account id, or user-id. **Should not contain the : character since we use it as a delimiter internally**
|
||||
- `product`: Jackson support multiple products, this is a unique identifier you set from your side that relates back to the product your customer is using. **Should not contain the : character since we use it as a delimiter internally**
|
||||
- `name`: A friendly name to identify the SAML connection
|
||||
- `description`: A short description with some information of the connection
|
||||
|
||||
The response returns a JSON with `clientID` and `clientSecret` that can be stored against your tenant and product for a more secure OAuth 2.0 flow. If you do not want to store the `clientID` and `clientSecret` you can alternatively use `client_id=tenant=<tenantID>&product=<productID>` and use `dummy` (or the value you set for the [secret verifier](../deploy/env-variables.md#client_secret_verifier) env) as the value for `client_secret` when setting up the OAuth 2.0 flow. Additionally a `idpMetadata.provider` attribute is also returned which indicates the domain of your Identity Provider.
|
||||
</TabItem>
|
||||
<TabItem value="oidc" label="OIDC">
|
||||
|
||||
Once your customer has set up the [OIDC app](../sso-providers/generic-oidc.md) on their Identity Provider, the Identity Provider will generate a clientId and clientSecret.
|
||||
|
||||
The following API call sets up the connection in Jackson:
|
||||
|
||||
```bash
|
||||
curl --location --request POST 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'defaultRedirectUrl=http://localhost:3366/login/oidc' \
|
||||
--data-urlencode 'oidcDiscoveryUrl=<well-known url of OIDC Provider>' \
|
||||
--data-urlencode 'oidcClientId=<clientId of IdP Registered App>' \
|
||||
--data-urlencode 'oidcClientSecret=<clientSecret of IdP Registered App>' \
|
||||
--data-urlencode 'redirectUrl=http://localhost:3366/*' \
|
||||
--data-urlencode 'redirectUrl=http://localhost:3000/*' \
|
||||
--data-urlencode 'tenant=boxyhq.com' \
|
||||
--data-urlencode 'product=demo' \
|
||||
--data-urlencode 'name=demo-connection' \
|
||||
--data-urlencode 'description=Demo OIDC connection'
|
||||
```
|
||||
|
||||
- `oidcDiscoveryUrl`: OpenID Providers supporting discovery make the metadata available at the endpoint obtained by concatenating issuer and `/.well-known/openid-configuration`
|
||||
- `oidcClientId`: The client identifier issued to the client during the IdP registration process.
|
||||
- `oidcClientSecret`: The client secret issued to the client during the IdP registration process.
|
||||
- `defaultRedirectUrl`: The redirect URL to use in the IdP login flow. Jackson will call this URL after completing an IdP login flow
|
||||
- `redirectUrl`: Allowed redirect URL. Repeat this field multiple times to allow multiple redirect URLs. Jackson will disallow any redirects not on this list (or not the default URL above).
|
||||
- `tenant`: Jackson supports a multi-tenant architecture, this is a unique identifier you set from your side that relates back to your customer's tenant. This is normally an email, domain, an account id, or user-id. **Should not contain the : character since we use it as a delimiter internally**
|
||||
- `product`: Jackson support multiple products, this is a unique identifier you set from your side that relates back to the product your customer is using. **Should not contain the : character since we use it as a delimiter internally**
|
||||
- `name`: A friendly name to identify the OIDC connection
|
||||
- `description`: A short description with some information of the connection
|
||||
|
||||
The response returns a JSON with `clientID` and `clientSecret` that can be stored against your tenant and product for a more secure OAuth 2.0 flow. If you do not want to store the `clientID` and `clientSecret` you can alternatively use `client_id=tenant=<tenantID>&product=<productID>` and use `dummy` (or the value you set for the [secret verifier](../deploy/env-variables.md#client_secret_verifier) env) as the value for `client_secret` when setting up the OAuth 2.0 flow. Additionally a `idpMetadata.provider` attribute is also returned which indicates the domain of your Identity Provider.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### 2.2 Get connections
|
||||
|
||||
This endpoint can be used to retrieve SAML/OIDC connections configured for a tenant/product. This can be used to check and display the details to your customers. You can use either `clientID` or `tenant` and `product` combination.
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="saml" label="SAML" default>
|
||||
|
||||
```bash
|
||||
curl -G --location 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'tenant=boxyhq.com' \
|
||||
--data-urlencode 'product=demo'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -G --location 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'clientID=<Client ID>'
|
||||
```
|
||||
|
||||
The response returns a JSON with `idpMetadata.provider`indicating the domain of your Identity Provider. If an empty JSON payload is returned then we do not have any connection stored for the attributes you requested.
|
||||
</TabItem>
|
||||
<TabItem value="oidc" label="OIDC">
|
||||
|
||||
```bash
|
||||
curl -G --location 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'tenant=boxyhq.com' \
|
||||
--data-urlencode 'product=demo'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -G --location 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'clientID=<Client ID>'
|
||||
```
|
||||
|
||||
The response returns a JSON with `oidcProvider.provider` indicating the domain of your Identity Provider. If an empty JSON payload is returned then we do not have any connection stored for the attributes you requested.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### 2.3 Update connection
|
||||
|
||||
This endpoint can be used to update an existing SSO Connection.
|
||||
<Tabs>
|
||||
<TabItem value="saml" label="SAML" default>
|
||||
|
||||
```bash
|
||||
curl --location --request PATCH 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'clientID=<Client ID>' \ /* Required */
|
||||
--data-urlencode 'clientSecret=<Client Secret>' \ /* Required */
|
||||
--data-urlencode 'encodedRawMetadata=Base64(<IdP/SP metadata XML>)' \
|
||||
--data-urlencode 'defaultRedirectUrl=http://localhost:3366/login/saml' \
|
||||
--data-urlencode 'redirectUrl=http://localhost:3366/*' \
|
||||
--data-urlencode 'redirectUrl=http://localhost:3000/*' \
|
||||
--data-urlencode 'tenant=boxyhq.com' \ /* Required */
|
||||
--data-urlencode 'product=demo' \ /* Required */
|
||||
--data-urlencode 'name=demo-connection' \
|
||||
--data-urlencode 'description=Demo SAML connection'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="oidc" label="OIDC" default>
|
||||
|
||||
```bash
|
||||
curl --location --request PATCH 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--data-urlencode 'clientID=<Client ID>' \ /* Required */
|
||||
--data-urlencode 'clientSecret=<Client Secret>' \ /* Required */
|
||||
--data-urlencode 'oidcDiscoveryUrl=<well-known url of OIDC Provider>' \
|
||||
--data-urlencode 'oidcClientId=<clientId of IdP Registered App>' \
|
||||
--data-urlencode 'oidcClientSecret=<clientSecret of IdP Registered App>' \
|
||||
--data-urlencode 'defaultRedirectUrl=http://localhost:3366/login/oidc' \
|
||||
--data-urlencode 'redirectUrl=http://localhost:3366/*' \
|
||||
--data-urlencode 'redirectUrl=http://localhost:3000/*' \
|
||||
--data-urlencode 'tenant=boxyhq.com' \ /* Required */
|
||||
--data-urlencode 'product=demo' \ /* Required */
|
||||
--data-urlencode 'name=demo-connection' \
|
||||
--data-urlencode 'description=Demo OIDC connection'
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### 2.4 Delete connections
|
||||
|
||||
This endpoint can be used to delete existing connections either by tenant/product or clientID.
|
||||
|
||||
```bash
|
||||
curl -X "DELETE" --location 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--url-query 'tenant=boxyhq.com' \
|
||||
--url-query 'product=demo'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -X "DELETE" --location 'http://localhost:5225/api/v1/connections' \
|
||||
--header 'Authorization: Api-Key <Jackson API Key>' \
|
||||
--url-query 'clientID=<Client ID>'
|
||||
--url-query 'clientSecret=<Client Secret>'
|
||||
```
|
||||
|
||||
## 3. OAuth 2.0 Flow
|
||||
|
||||
:::info
|
||||
|
||||
#### OpenID Connect flow
|
||||
|
||||
Jackson also supports the [OIDC flow](https://openid.net/specs/openid-connect-core-1_0.html). By including `openid` in the `scope` param, an additional `id_token` is returned from the token endpoint which contains the user claims: `id, email, firstName, and lastName`. To enable the flow on Jackson, be sure to configure the keys and algorithm in [OpenID configuration](../deploy/env-variables.md#openid-configuration). If the authentication request contained `nonce` then it is passed unmodified to the ID Token, which the client can use to validate and mitigate replay attacks.
|
||||
:::
|
||||
|
||||
Jackson has been designed to abstract the underlying SAML/OIDC login flow as a pure OAuth 2.0 flow. This means it's compatible with any standard OAuth 2.0 library out there, both client-side and server-side. It is important to remember that SSO Connection is configured per customer unlike OAuth 2.0 where you can have a single OAuth app supporting logins for all customers.
|
||||
|
||||
Jackson also supports the PKCE authorization flow (<https://oauth.net/2/pkce/>), so you can protect your SPAs.
|
||||
|
||||
If for any reason you need to implement the flow on your own, the steps are outlined below:
|
||||
|
||||
### 3.1 Authorize
|
||||
|
||||
The OAuth flow begins with redirecting your user to the `authorize` URL:
|
||||
|
||||
```bash
|
||||
https://localhost:5225/api/oauth/authorize
|
||||
?response_type=code&provider=saml
|
||||
&client_id=<clientID or tenant and product query params as described in the SSO connection API section above>
|
||||
&redirect_uri=<redirect URL>
|
||||
&state=<randomly generated state id>
|
||||
```
|
||||
|
||||
- `response_type`: `code` is the only supported type for now but maybe extended in the future
|
||||
- `client_id`: Use the client_id returned by the SSO connection API or use `tenant=<tenantID>&product=<productID>` to use the tenant and product IDs instead. **Note:** Please don't forget to URL encode the query parameters including `client_id`.
|
||||
- `tenant`: Optionally you can provide use `dummy` as the value for `client_id` and specify the `tenant` and `product` custom attributes (if your OAuth 2.0 library allows it).
|
||||
- `product`: Should be specified if specifying `tenant` above
|
||||
- `idp_hint`: Can be used to select the Identity Provider if multiple connections match for the same `tenant/product`. Should point to the absolute "clientID" of the SSO Connection in Jackson.
|
||||
- `redirect_uri`: This is where the user will be taken back once the authorization flow is complete
|
||||
- `state`: Use a randomly generated string as the state, this will be echoed back as a query parameter when taking the user back to the `redirect_uri` above. You should validate the state to prevent XSRF attacks.
|
||||
- `nonce` (for OIDC flow): String value used to associate a Client session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. Sufficient entropy MUST be present in the nonce values used to prevent attackers from guessing values.
|
||||
- `forceAuthn` (for SAML SSO Connections): If passed in with the value `true`, the outgoing SAML request to IdP will have the param `ForceAuthn` set as true forcing the user to re-authenticate even if they have an active session.
|
||||
- `login_hint` (Relevant for OIDC IdPs like Google): If passed in, the parameter will be forwarded in the OIDC IdP authorize request. The IdP can use this value (normally an account identifier such as an email address) as a hint to skip the account selection page.
|
||||
|
||||
**NOTE**: You can also pass the encoded tenant/product in either `scope` or `access_type` or `resource` (Set `client_id` as `dummy`). This will come in handy for some setups where the client_id can't be set dynamically.
|
||||
|
||||
The user will be taken to the IdP based on the configured SAML/OIDC metadata.
|
||||
In case of any errors, we return the `error`, `error_description` and `state` (from original request) (see [Error Response](https://www.oauth.com/oauth2-servers/authorization/the-authorization-response/)) back to the `redirect_uri` (`redirect_uri` is validated against the saml connection to prevent open redirects).
|
||||
|
||||
### 3.2 Code Exchange
|
||||
|
||||
Once the user logs in successfully at the IdP, IdP sends back the SAML/OIDC response to Jackson. For SAML, the response contains the user profile. In the case of OIDC, the response contains the authorization code that is used by Jackson to obtain token and userprofile from the OIDC IdP. Jackson generates a short lived `code` and stores the user profile against it. After successful authorization, the user is redirected back to the `redirect_uri`. The query parameters will include the `code` and `state` parameters. You should validate that the state matches the one you sent in the `authorize` request.
|
||||
|
||||
The code can then be exchanged for a token by making the following request:
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url 'http://localhost:5225/api/oauth/token' \
|
||||
--header 'content-type: application/x-www-form-urlencoded' \
|
||||
--data 'grant_type=authorization_code' \
|
||||
--data 'client_id=<clientID or tenant and product query params as described in the SAML connection API section above>' \
|
||||
--data 'client_secret=<clientSecret or any arbitrary value if using the tenant and product in the clientID>' \
|
||||
--data 'redirect_uri=<redirect URL>' \
|
||||
--data 'code=<code from the query parameter above>'
|
||||
```
|
||||
|
||||
- `grant_type`: `authorization_code` is the only supported flow, for now. We might extend this in the future
|
||||
- `client_id`: Use the client_id returned by the SSO connection API or use `tenant=<tenantID>&product=<productID>` to use the tenant and product IDs instead. **Note:** Please don't forget to URL encode the query parameters including `client_id`.
|
||||
- `client_secret`: Use the client_secret returned by the SAML connection API or any arbitrary value if using the tenant and product in the clientID
|
||||
- `redirect_uri`: This is where the user will be taken back once the authorization flow is complete. Use the same redirect_uri as the previous request
|
||||
|
||||
If everything goes well you should receive a JSON response that includes the access token. This token is needed for the next step where we fetch the user profile.
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": <access token>,
|
||||
"token_type": "bearer",
|
||||
"expires_in": 300
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 Profile Request
|
||||
|
||||
The short-lived access token can now be used to request the user's profile. You'll need to make the following request:
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'https://localhost:5225/api/oauth/userinfo' \
|
||||
--header 'authorization: Bearer <access token>'
|
||||
```
|
||||
|
||||
If everything goes well you should receive a JSON response with the user's profile:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": <id from the Identity Provider>,
|
||||
"email": "sjackson@coolstartup.com",
|
||||
"firstName": "SAML",
|
||||
"lastName": "Jackson"
|
||||
"raw": {
|
||||
...
|
||||
},
|
||||
"requested": {
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `id`: The id of the user as provided by the Identity Provider. (SAML SLO request requires you to pass `id` as `nameId`. Save `id` if you have a plan to implement SLO in the future.)
|
||||
- `email`: The email address of the user as provided by the Identity Provider
|
||||
- `firstName`: The first name of the user as provided by the Identity Provider
|
||||
- `lastName`: The last name of the user as provided by the Identity Provider
|
||||
- `raw`: This contains all claims attributes returned by the SAML provider
|
||||
- `requested`: This contains the `tenant`, `product`, `client_id` and `state` from the authorize request. It can be used to reconcile context on the client side if needed
|
||||
|
||||
## 4. SAML SLO
|
||||
|
||||
SLO is a SAML flow that allows an end-user to logout of a single session and be automatically logged out of all linked sessions created during the SSO process.
|
||||
|
||||
The SLO flow begins with redirecting your user to the `/api/logout` endpoint.
|
||||
|
||||
```bash
|
||||
https://localhost:5225/api/logout
|
||||
?nameId=google-auth0-f92cc1834efc0f73e9c09
|
||||
&tenant=boxyhq.com
|
||||
&product=demo
|
||||
&redirectUrl=http://www.example.com/logout
|
||||
```
|
||||
|
||||
- `nameId`: Identifies the subject of a SAML assertion (Typically the user who is authenticated)
|
||||
- `tenant`: The tentant
|
||||
- `product`: The product
|
||||
- `redirectUrl`: Post logout redirect URL
|
||||
|
||||
IdP will send a response (as a POST operation) to a specific URL (Single Logout URL) for the logout request. You need to register this URL on the IdP `/api/logout/callback` to handle the response.
|
||||
|
||||
Jackson will redirect users to `redirectUrl` after the successful logout.
|
||||
|
||||
:::info
|
||||
You should save the `id` returned by the `userinfo` for an user so that you can use the `id` as `nameId` with SLO request.
|
||||
:::
|
@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for Auth0 SAML
|
||||
sidebar_label: Auth0 SAML
|
||||
---
|
||||
|
||||
# Auth0 SAML SSO
|
||||
|
||||
In this section, we will show you how to set up your own custom SAML application for Auth0 SAML.
|
||||
|
||||
## Create Application
|
||||
|
||||
From your Auth0 dashboard, click **Applications** from the left navigation menu.
|
||||
|
||||
If your application is already created, choose it from the list and move to the section [Configure Application](#configure-application)
|
||||
|
||||

|
||||
|
||||
If you haven't created a SAML application, click the **Create Application** button to create a new application.
|
||||
|
||||
Give your application a **Name** and click **Create**.
|
||||
|
||||

|
||||
|
||||
## Configure Application
|
||||
|
||||
Click the tab **Addons** and enable **SAML2 WEB APP** addon.
|
||||
|
||||

|
||||
|
||||
Enter your **Application Callback URL** on the next screen and click **Enable**.
|
||||
|
||||
Replace the values with the ones you have received from SAML Jackson.
|
||||
|
||||

|
||||
|
||||
Click the tab **Usage** and download the **Identity Provider Metadata**.
|
||||
|
||||

|
||||
|
||||
## Attribute Mapping
|
||||
|
||||
No additional attribute mapping is required for Auth0 SAML to work with SAML Jackson.
|
||||
|
||||
## Next steps
|
||||
|
||||
You've successfully configured your custom SAML application for Auth0 SAML. At this stage, you can assign users to your application and start using it.
|
||||
|
||||
## Resources
|
||||
|
||||
- [Auth0 Doc](https://auth0.com/docs)
|
||||
|
||||
:::tip
|
||||
Got a question? [Ask here](https://discord.gg/uyb7pYt4Pa)
|
||||
:::
|
@ -0,0 +1,80 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for Azure AD SAML
|
||||
sidebar_label: Azure AD SAML
|
||||
---
|
||||
|
||||
# Azure AD SAML SSO
|
||||
|
||||
In this section, we will show you how to set up your own custom SAML application for Azure AD SAML.
|
||||
|
||||
## Create Application
|
||||
|
||||
From your Azure Admin console, click **Enterprise applications** from the left navigation menu.
|
||||
|
||||

|
||||
|
||||
If your application is already created, choose it from the list and move to the section [Configure Application](#configure-application)
|
||||
|
||||
If you haven't created a SAML application, click **New application** from the top to create a new application.
|
||||
|
||||

|
||||
|
||||
From the next screen, click **Create your own application**. Give your application a **Name** and click **Create**.
|
||||
|
||||

|
||||
|
||||
## Configure Application
|
||||
|
||||
Select **Single Sign On** from the **Manage** section of your app and then **SAML**.
|
||||
|
||||

|
||||
|
||||
Click **Edit** on the **Basic SAML Configuration** section.
|
||||
|
||||

|
||||
|
||||
Enter the following values in the **Basic SAML Configuration** section on the next screen:
|
||||
|
||||
- **Identifier (Entity ID)**
|
||||
- **Reply URL (Assertion Consumer Service URL)**
|
||||
|
||||
Replace the values with the ones you have received from SAML Jackson.
|
||||
|
||||
Click **Save** to save your changes.
|
||||
|
||||

|
||||
|
||||
## Attribute Mapping
|
||||
|
||||
Click **Edit** on the **Attributes & Claims** section.
|
||||
|
||||

|
||||
|
||||
You have to configure the following attributes under the **Attributes & Claims** section:
|
||||
|
||||
| Name | Value |
|
||||
| -------------------------------------------------------------------- | ---------------------- |
|
||||
| `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress` | user.mail |
|
||||
| `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname` | user.givenname |
|
||||
| `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name` | user.userprincipalname |
|
||||
| `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname` | user.surname |
|
||||
|
||||
See the screenshot below.
|
||||
|
||||

|
||||
|
||||
Go to the section **SAML Signing Certificate** section and download the **Federation Metadata XML**.
|
||||
|
||||

|
||||
|
||||
## Next steps
|
||||
|
||||
You've successfully configured your custom SAML application for Azure AD SAML. At this stage, you can assign users to your application and start using it.
|
||||
|
||||
## Resources
|
||||
|
||||
- [Azure Admin Console](https://portal.azure.com/)
|
||||
|
||||
:::tip
|
||||
Got a question? [Ask here](https://discord.gg/uyb7pYt4Pa)
|
||||
:::
|
@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Set up app in your OpenID Connect Identity Provider
|
||||
sidebar_label: OpenID Connect Provider
|
||||
---
|
||||
|
||||
# OIDC Provider setup
|
||||
|
||||
To allow apps or clients to login using an OIDC Identity Provider, we must register an application with the IdP. The process might slightly vary from one IdP to another (refer your IdP documentation), but there are a few things in common.
|
||||
|
||||
- **Callback URL**: This will be the URL where Jackson receives the OIDC Authorization response. Make sure to set the full HTTPS URL obtained by concatenating Jackson endpoint with [oidcPath](../deploy/env-variables.md#oidc_path) env. The default value set for `oidcPath` in Jackson service is `/api/oauth/oidc`.
|
||||
- **Client/Application ID**: The OIDC Identity Provider normally will generate a unique identifier for the registered App. Make a note of this to be used later when creating the SSO connection with Jackson.
|
||||
- **Client Secret**: Along with the Client ID, the IdP also generates a client secret which is used to authenticate the client while issuing tokens. Make a note of this to be used later when creating the SSO connection with Jackson.
|
||||
|
||||
:::info
|
||||
Since Jackson acts as a proxy between the app and the OIDC Identity Provider, here the application/client is Jackson.
|
||||
:::
|
@ -0,0 +1,73 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for Google SAML
|
||||
sidebar_label: Google SAML
|
||||
---
|
||||
|
||||
# Google SAML SSO
|
||||
|
||||
In this section, we will show you how to set up your own custom SAML application for Google SAML.
|
||||
|
||||
## Create Application
|
||||
|
||||
From your Google Admin console, click **Apps** from the sidebar then click **Web and mobile apps** from the list.
|
||||
|
||||
If your application is already created, choose it from the list and move to the section [Configure Application](#configure-application)
|
||||
|
||||
If you haven't created a SAML application, click **Add custom SAML app** from the menu.
|
||||
|
||||

|
||||
|
||||
Give your application an **App name** and click **Continue**.
|
||||
|
||||

|
||||
|
||||
## Configure Application
|
||||
|
||||
From the next screen, click **DOWNLOAD METADATA** to download the metadata XML file, then click **Continue**.
|
||||
|
||||

|
||||
|
||||
Enter the following values in the **Service provider details** section:
|
||||
|
||||
- **ACS URL**
|
||||
- **Entity ID**
|
||||
|
||||
Replace the values with the ones you have received from SAML Jackson and click **Continue** to save the configuration.
|
||||
|
||||

|
||||
|
||||
## Attribute Mapping
|
||||
|
||||
Under the **Attributes** section, you have to configure the following attributes:
|
||||
|
||||
| App attributes | Google directory attributes |
|
||||
| -------------- | --------------------------- |
|
||||
| email | Primary email |
|
||||
| firstName | First name |
|
||||
| lastName | Last name |
|
||||
|
||||
See the screenshot below.
|
||||
|
||||
After you have configured the attributes, click **Finish** to save the configuration.
|
||||
|
||||

|
||||
|
||||
From the next screen, click **User access** to configure the application to allow users to log in.
|
||||
|
||||

|
||||
|
||||
Check the **ON for everyone** checkbox and click **Save**.
|
||||
|
||||

|
||||
|
||||
## Next steps
|
||||
|
||||
You've successfully configured your custom SAML application for Google SAML. At this stage, you can assign users to your application and start using it.
|
||||
|
||||
## Resources
|
||||
|
||||
- [Google Admin Console](https://admin.google.com/)
|
||||
|
||||
:::tip
|
||||
Got a question? [Ask here](https://discord.gg/uyb7pYt4Pa)
|
||||
:::
|
@ -0,0 +1,20 @@
|
||||
---
|
||||
title: SAML SSO Providers
|
||||
sidebar_label: SSO Providers
|
||||
---
|
||||
|
||||
# SAML SSO Providers
|
||||
|
||||
SAML Jackson supports the following SSO providers:
|
||||
|
||||
- [Generic SAML 2.0 Provider](./generic-saml.md)
|
||||
- [Azure](./azure.md)
|
||||
- [Microsoft AD FS](./microsoft-adfs.md)
|
||||
- [Okta](./okta.md)
|
||||
- [Auth0](./auth0.md)
|
||||
- [Google](./google.md)
|
||||
- [OneLogin](./onelogin.md)
|
||||
- [PingOne](./pingone.md)
|
||||
- [JumpCloud](./jumpcloud.md)
|
||||
- [Rippling](./rippling.md)
|
||||
- [OpenID Connect Provider](./generic-oidc.md)
|
@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for JumpCloud SAML
|
||||
sidebar_label: JumpCloud SAML
|
||||
---
|
||||
|
||||
# JumpCloud SAML SSO
|
||||
|
||||
In this section, we will show you how to set up your own custom SAML application for JumpCloud SAML.
|
||||
|
||||
## Create Application
|
||||
|
||||
From your JumpCloud Admin console, click **SSO** from the left navigation menu.
|
||||
|
||||
If your application is already created, choose it from the list and move to the section [Configure Application](#configure-application)
|
||||
|
||||
If you haven't created a SAML application, click plus icon and then **Custom SAML App** to create a new application
|
||||
|
||||

|
||||
|
||||
Give your application a **Display Label**.
|
||||
|
||||

|
||||
|
||||
## Configure Application
|
||||
|
||||
Next click on the **SSO** tab and enter the following values:
|
||||
|
||||
- **IdP Entity ID**
|
||||
- **SP Entity ID**
|
||||
- **ACS URL**
|
||||
|
||||
Replace the values with the ones you have received from SAML Jackson.
|
||||
|
||||

|
||||
|
||||
## Attribute Mapping
|
||||
|
||||
Under the **Attributes** section, you have to configure the following attributes:
|
||||
|
||||
See the screenshot below.
|
||||
|
||||
| Service Provider Attribute Name | JumpCloud Attribute Name |
|
||||
| ------------------------------- | ------------------------ |
|
||||
| email | email |
|
||||
| firstName | firstname |
|
||||
| lastName | lastname |
|
||||
|
||||
Make sure you have checked the **Declare Redirect Endpoint** checkbox.
|
||||
|
||||
Finally, click **Activate** to save the application configuration.
|
||||
|
||||

|
||||
|
||||
Now go back to the SAML app you just created, click the tab **SSO**, and click the button **Export Metadata** to download the metadata XML file.
|
||||
|
||||

|
||||
|
||||
## Next steps
|
||||
|
||||
You've successfully configured your custom SAML application for JumpCloud. At this stage, you can assign users to your application and start using it.
|
||||
|
||||
## Resources
|
||||
|
||||
- [JumpCloud](https://jumpcloud.com/) official website
|
||||
|
||||
:::tip
|
||||
Got a question? [Ask here](https://discord.gg/uyb7pYt4Pa)
|
||||
:::
|
@ -0,0 +1,51 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for Microsoft AD FS
|
||||
sidebar_label: Microsoft AD FS
|
||||
---
|
||||
|
||||
# Microsoft AD FS SAML SSO
|
||||
|
||||
In this section, we will show you how to set up your own custom SAML application for Microsoft AD FS.
|
||||
|
||||
In AD FS, a relying party (RP) trust needs to be set up. You can supply our SP metadata file, usually located at `https://<your-hosted-url>/.well-known/sp-metadata` and let AD FS automatically pick up the configuration.
|
||||
|
||||
If you are manually entering the details then you'll find the details you need in [this section](./generic-saml.md). The public certificate is needed for Signature verification and is usually located at `https://<your-hosted-url>/.well-known/saml.cer` for Signature verification.
|
||||
|
||||
You will also need to map some attributes of the claims so we can fetch the profile information for your user.
|
||||
|
||||
## Create a claims aware Relying Party Trust using federation metadata
|
||||
|
||||
1. In Server Manager, click Tools, and then select AD FS Management.
|
||||
2. Under Actions, click Add Relying Party Trust.
|
||||

|
||||
3. On the Welcome page, choose Claims aware and click Start.
|
||||

|
||||
4. On the Select Data Source page, click Import data about the relying party published online or on a local network. In Federation metadata address (host name or URL), type the federation metadata URL or host name for the partner, and then click Next.
|
||||

|
||||
5. On the Specify Display Name page type a name in Display name, under Notes type a description for this relying party trust, and then click Next.
|
||||
6. On the Choose Issuance Authorization Rules page, select either Permit all users to access this relying party or Deny all users access to this relying party, and then click Next.
|
||||
7. On the Ready to Add Trust page, review the settings, and then click Next to save your relying party trust information.
|
||||
8. On the Finish page, click Close. This action automatically displays the Edit Claim Rules dialog box.
|
||||
9. **Mapping attributes**:
|
||||
On the Configure Claim Rule screen, enter a Claim Rule Name of your choice, select Active Directory as the Attribute Store, then add the following mapping:
|
||||
|
||||
- From the LDAP Attribute column, select `E-Mail-Addresses`. From the Outgoing Claim Type, type `E-Mail Address`.
|
||||
- From the LDAP Attribute column, select `Given-Name`. From the Outgoing Claim Type, type `Given Name`.
|
||||
- From the LDAP Attribute column, select `Surname`. From the Outgoing Claim Type, type `Surname`.
|
||||
- From the LDAP Attribute column, select `User-Principal-Name`. From the Outgoing Claim Type, type `Name ID`.
|
||||
|
||||
10. **Transform Rule**: Create a transform rule mapping the incoming `Email-Address` to outgoing `NameID` (of type `Email`), ADFS by default sends `NameID` as `Unspecified` which results in an `InvalidNameIDPolicy` error if this step is missed.
|
||||
|
||||

|
||||
|
||||
If you'd rather use Claim rule language then the following rule can be applied:
|
||||
|
||||
```sh
|
||||
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"] => issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
|
||||
```
|
||||
|
||||
11. Finally open Windows PowerShell as an administrator, then run the following command:
|
||||
|
||||
```sh
|
||||
Set-ADFSRelyingPartyTrust -TargetName <display-name> -SamlResponseSignature "MessageAndAssertion"
|
||||
```
|
@ -0,0 +1,76 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for Okta SAML
|
||||
sidebar_label: Okta SAML
|
||||
---
|
||||
|
||||
# Okta SAML SSO
|
||||
|
||||
In this section, we will show you how to set up your own custom SAML application for Okta SAML.
|
||||
|
||||
## Create Application
|
||||
|
||||
From your Okta account, click **Applications** from the left navigation menu.
|
||||
|
||||
If your application is already created, choose it from the list and move to the section [Configure Application](#configure-application)
|
||||
|
||||
If you haven't created a SAML application, click the **Create App Integration** button to create a new application.
|
||||
|
||||

|
||||
|
||||
Choose **SAML 2.0** from the next screen and click **Next**.
|
||||
|
||||

|
||||
|
||||
Give your application an **App Name** and click **Next**.
|
||||
|
||||

|
||||
|
||||
## Configure Application
|
||||
|
||||
Enter the following values in the **SAML Settings** section on the next screen:
|
||||
|
||||
- **Single sign on URL**
|
||||
- **Audience URI (SP Entity ID)**
|
||||
- Select **EmailAddress** from the **Name ID format** dropdown.
|
||||
|
||||
Replace the values with the ones you have received from SAML Jackson.
|
||||
|
||||

|
||||
|
||||
## Attribute Mapping
|
||||
|
||||
Under the **Attribute Statements** section, you have to configure the following attributes:
|
||||
|
||||
| Name | Value |
|
||||
| --------- | -------------- |
|
||||
| id | user.id |
|
||||
| email | user.email |
|
||||
| firstName | user.firstName |
|
||||
| lastName | user.lastName |
|
||||
|
||||
See the screenshot below.
|
||||
|
||||

|
||||
|
||||
On the next screen select **I'm an Okta customer adding an internal app** and click **Finish**.
|
||||
|
||||

|
||||
|
||||
From your application, click **Sign On** tab and go to the section **SAML Signing Certificates**
|
||||
|
||||
Click the **Actions** dropdown for the correct certificate and click **View IdP metadata**. A separate window will open with the metadata XML file, you can copy it to your clipboard.
|
||||
|
||||

|
||||
|
||||
## Next steps
|
||||
|
||||
You've successfully configured your custom SAML application for Okta SAML. At this stage, you can assign users to your application and start using it.
|
||||
|
||||
## Resources
|
||||
|
||||
- [Okta](https://www.okta.com/) official website
|
||||
- Visit [Okta documentation](https://developer.okta.com/docs/concepts/saml/)
|
||||
|
||||
:::tip
|
||||
Got a question? [Ask here](https://discord.gg/uyb7pYt4Pa)
|
||||
:::
|
@ -0,0 +1,91 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for OneLogin SAML
|
||||
sidebar_label: OneLogin SAML
|
||||
---
|
||||
|
||||
# OneLogin SAML SSO
|
||||
|
||||
In this section, we will show you how to set up your own custom SAML application for OneLogin SAML.
|
||||
|
||||
## Create Application
|
||||
|
||||
From your OneLogin account, click **Applications** from the top navigation menu.
|
||||
|
||||
If your application is already created, choose it from the list and move to the section [Configure Application](#configure-application)
|
||||
|
||||
If you haven't created a SAML application, click the **Add App** button to create a new application.
|
||||
|
||||

|
||||
|
||||
Search for **SAML Test Connector** in the **Find Applications** section. Select **SAML Custom Connector (Advanced)** from the search results.
|
||||
|
||||

|
||||
|
||||
Give your application a **Display Name** and click **Save**.
|
||||
|
||||

|
||||
|
||||
## Configure Application
|
||||
|
||||
From your application, click the **Configuration** tab on the left to configure the application.
|
||||
|
||||
You have to enter the following values in the **Application details** section:
|
||||
|
||||
- **Audience (Entity ID)**
|
||||
- **ACS (Consumer) URL Validator**
|
||||
- **ACS (Consumer) URL**
|
||||
- Select the **Service Provider** from the **SAML initiator** dropdown.
|
||||
|
||||
Replace the values with the ones you have received from SAML Jackson.
|
||||
|
||||
Click **Save** to save the configuration.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Click the dropdown menu **More Actions** from the top right corner and click **SAML Metadata** to download the metadata XML file.
|
||||
|
||||

|
||||
|
||||
## Attribute Mapping
|
||||
|
||||
From your application, click the **Parameters** tab on the left.
|
||||
|
||||
You have to configure the following attributes:
|
||||
|
||||
| SAML Custom Connector Field | Value |
|
||||
| --------------------------- | ---------- |
|
||||
| id | UUID |
|
||||
| email | Email |
|
||||
| firstName | First Name |
|
||||
| lastName | Last Name |
|
||||
|
||||
See the screenshot below.
|
||||
|
||||

|
||||
|
||||
See the below screenshot to see how to map the **id** attribute to **UUID**.
|
||||
|
||||
Enter **id** in the **Field name** input and check the **Include in SAML assertion** checkbox. Click **Save** to continue.
|
||||
|
||||

|
||||
|
||||
On the next screen, select **UUID** from the **Value** dropdown and click **Save**.
|
||||
|
||||

|
||||
|
||||
Do the same for the other attributes (email, firstName, lastName).
|
||||
|
||||
## Next steps
|
||||
|
||||
You've successfully configured your custom SAML application for OneLogin SAML. At this stage, you can assign users to your application and start using it.
|
||||
|
||||
## Resources
|
||||
|
||||
- [OneLogin](https://www.onelogin.com/) official website
|
||||
- Visit [OneLogin documentation](https://developers.onelogin.com/)
|
||||
|
||||
:::tip
|
||||
Got a question? [Ask here](https://discord.gg/uyb7pYt4Pa)
|
||||
:::
|
@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for PingOne SAML
|
||||
sidebar_label: PingOne SAML
|
||||
---
|
||||
|
||||
# PingOne SAML SSO
|
||||
|
||||
In this section, we will show you how to set up your own custom SAML application for PingOne SAML.
|
||||
|
||||
## Create Application
|
||||
|
||||
From your PingOne account, click **Connections** > **Applications** from left navigation menu.
|
||||
|
||||
If your application is already created, choose it from the list and move to the section [Configure Application](#configure-application)
|
||||
|
||||
If you haven't created a SAML application, click plus button to create a new application.
|
||||
|
||||

|
||||
|
||||
Give your application a **Application Name**, choose **SAML Application** from the **Application Type** and click **Configure**.
|
||||
|
||||
## Configure Application
|
||||
|
||||

|
||||
|
||||
From the next screen, you have to enter the following values in the **SAML Configuration** section:
|
||||
|
||||
- **ACS URLs**
|
||||
- **Entity ID**
|
||||
|
||||
Replace the values with the ones you have received from SAML Jackson.
|
||||
|
||||
Click **Save** to save the configuration.
|
||||
|
||||

|
||||
|
||||
Click the **Configuration** tab from the top and click **Download Metadata** to download the metadata XML file.
|
||||
|
||||

|
||||
|
||||
## Attribute Mapping
|
||||
|
||||
Click the **Attribute Mappings** tab from the top and you have to configure the following attributes:
|
||||
|
||||
| SAML App | PingOne |
|
||||
| --------- | ------------- |
|
||||
| id | User ID |
|
||||
| email | Email Address |
|
||||
| firstName | Given Name |
|
||||
| lastName | Family Name |
|
||||
|
||||
See the screenshot below.
|
||||
|
||||

|
||||
|
||||
Make sure you have enabled your app so that it can be used by the users. You can do this by clicking the **Toggle** button next to your app.
|
||||
|
||||

|
||||
|
||||
## Next steps
|
||||
|
||||
You've successfully configured your custom SAML application for PingOne SAML. At this stage, you can assign users to your application and start using it.
|
||||
|
||||
## Resources
|
||||
|
||||
- [Ping Identity Website](https://www.pingidentity.com/en.html)
|
||||
- [Ping Identity Documentation](https://docs.pingidentity.com/)
|
||||
|
||||
:::tip
|
||||
Got a question? [Ask here](https://discord.gg/uyb7pYt4Pa)
|
||||
:::
|
@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Set up your own custom SAML application for Rippling SAML
|
||||
sidebar_label: Rippling SAML
|
||||
---
|
||||
|
||||
# Rippling SAML SSO
|
||||
|
||||
This section will show you how to set up your own custom SAML application for Rippling SAML.
|
||||
|
||||
## Create Application
|
||||
|
||||
You'll need to create a new **Custom App** from your Rippling account if the app is not already in the Rippling app directory.
|
||||
|
||||
Go to **IT Management** > **Custom App** from the left navigation menu.
|
||||
|
||||

|
||||
|
||||
Click **Create New App** button to create a new application.
|
||||
|
||||
From the next screen, fill in the following fields:
|
||||
|
||||
- **App Name**
|
||||
- **Select Categories**
|
||||
- **Upload Logo**
|
||||
- **What type of app would you like to create?** - Make sure you select **Single Sign-On (SAML)** from the list.
|
||||
|
||||

|
||||
|
||||
## Configure Application
|
||||
|
||||
Copy the **Idp Metadata URL** or **Idp Metadata XML** from the next screen. You'll need this value to configure your SAML connection in SAML Jackson.
|
||||
|
||||

|
||||
|
||||
You'll need to enter the **ACS URL** and **Entity ID**. You'll get these values from SAML Jackson.
|
||||
|
||||

|
||||
|
||||
Make sure that **Service Provider Entity ID** matches the **SAML Audience (SP Entity ID)** value from SAML Jackson.
|
||||
|
||||
From the **Settings** tab of custom app you just created. Go to **Advanced SAML Settings** section and check the box for **Disable InResponseTo field in assertions for IdP initiated SSO**.
|
||||
|
||||
This is because Rippling sends dummy values for the **InResponseTo** field and SAML Jackson will try to validate the **InResponseTo** field if it is present.
|
||||
|
||||

|
||||
|
||||
## Next steps
|
||||
|
||||
You've successfully configured your custom SAML application for Rippling SAML. At this stage, you can assign users to your application and start using it.
|
||||
|
||||
## Resources
|
||||
|
||||
- [Rippling](https://www.rippling.com/) official website
|
||||
- Visit [Rippling documentation](https://developer.rippling.com/)
|
||||
|
||||
:::tip
|
||||
Got a question? [Ask here](https://discord.gg/uyb7pYt4Pa)
|
||||
:::
|
@ -0,0 +1,35 @@
|
||||
# Upgrade Guide
|
||||
|
||||
## Upgrading to v1.11.0
|
||||
|
||||
We have patched the SSO connection (`/api/v1/connections`) DELETE handler to accept payload (client/Secret or tenant/product/strategy) as part of query parameters. Earlier, the payload was expected to be part of the body which is non-standard and is no longer supported in Next.js.
|
||||
|
||||
## Upgrading to v1.9.7
|
||||
|
||||
We discovered and fixed a database connection leak introduced in v1.9.1, if you are using versions 1.9.1 to 1.9.6 then please upgrade to v1.9.7
|
||||
|
||||
## Upgrading to v1.8.0
|
||||
|
||||
1. We support bringing your own database (BYOD), this is a very tricky feature to support and we are still iterating on the schema which works as seamlessly as possible across the range of databases we support. Unfortunately, not everything goes smoothly here and we have encountered some length issues on newer versions of MySQL and MariaDB. The best way forward was to change the schema of the keys we use from length 1500 to 250 which is compatible with the newer versions. As a result, this will break your updates if you are using MySQL, MariaDB, or MS SQL Server. If you encounter this please reach out and we'll guide you through the update process. If you haven't gone into production yet then please update to v1.8.0 before you deploy it to production.
|
||||
|
||||
## Upgrading to v1.3.10
|
||||
|
||||
1. For users of our npm library, `directorySync` has been renamed to `directorySyncController`.
|
||||
|
||||
## Upgrading to v1.3.6
|
||||
|
||||
1. `samlSPConfig.get()` is now async since we introduced a global certificate instead of per tenant certificate to ease the SAML setup process.
|
||||
|
||||
## Upgrading to v1.3.0
|
||||
|
||||
1. Landed support for OpenID Identity Providers.
|
||||
2. Landed new API (`/api/v1/connections`) to support setting up both SAML/OIDC SSO Connections.
|
||||
|
||||
**Note:** The previous API for SAML configuration `/api/v1/saml/config` has been deprecated, and would be completely removed in a future release.
|
||||
|
||||
3. Renamed env variable `PRE_LOADED_CONFIG` to [`PRE_LOADED_CONNECTION`](deploy/env-variables.md#pre_loaded_connection) for Jackson service. In the case of npm `preLoadedConfig` becomes`preLoadedConnection`.
|
||||
4. Make sure to set the value for [`oidcPath`](deploy/env-variables.md#oidc_path) in case you are using the npm.
|
||||
|
||||
## Backups
|
||||
|
||||
Please remember to take backups before upgrading Jackson. We cannot stress how important this step is, although we take precautions to avoid bugs they sometimes do slip by us. Having backups will not only help you recover from these rare events but should be part of your disaster recovery process. If you need any help with this please do not hesitate to reach out to us.
|
@ -0,0 +1,64 @@
|
||||
# Automated Audit Events
|
||||
|
||||
When an end customer uses a Viewer or Enterprise token to view logs directly from the Retraced API, Retraced will record the read event in your audit log.
|
||||
|
||||
You can configure these events with the optional `view_log_action` parameter when you create a new Viewer or Enterprise token through the Publisher API. The default action is "audit.log.view". Viewer tokens also require an `actor_id` parameter at creation time, while Enterprise token audit events generate an `actor.id` from the token.
|
||||
|
||||
## Viewer Example
|
||||
|
||||
Suppose a viewer token was created with `group_id=example.com`, `actor_id=user@example.com` and `action=viwer.view_logs`. When the token is used, an event like this will be inserted into your audit log:
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "viewer.view_logs",
|
||||
"crud": "r",
|
||||
"actor": {
|
||||
"id": "user@example.com"
|
||||
},
|
||||
"group": {
|
||||
"id": "example.com"
|
||||
},
|
||||
"description": "GET http://localhost:3000/auditlog/viewer/v1/graphql",
|
||||
"source_ip": "1.1.0.180"
|
||||
}
|
||||
```
|
||||
|
||||
## Enterprise Example
|
||||
|
||||
An Enterprise token created with `group_id` "example.com" and no `view_log_action` would generate an event similar to this when used:
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "audit.log.view",
|
||||
"crud": "r",
|
||||
"actor": {
|
||||
"id": "enterprise:1234567"
|
||||
},
|
||||
"group": {
|
||||
"id": "example.com"
|
||||
},
|
||||
"description": "GET http://localhost:3000/auditlog/enterprise/v1/graphql",
|
||||
"source_ip": "1.1.0.180"
|
||||
}
|
||||
```
|
||||
|
||||
## Viewer Enterprise Token Self-Management
|
||||
|
||||
Another instance where Viewers can perform actions bypassing your API is when creating, retrieiving, updating, or deleting their own Enterprise tokens. Retraced will add these events to your audit log on your behalf. Note that Retraced does not insert audit events when Enterprise tokens are managed through the Publisher API, since you have the option of sending your own audit events for these actions.
|
||||
|
||||
An example of an event logged when a Viewer creates their own Enterpise token is:
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "eitapi_token.create",
|
||||
"crud": "c",
|
||||
"actor": {
|
||||
"id": "user@example.com"
|
||||
},
|
||||
"group": {
|
||||
"id": "example.com"
|
||||
},
|
||||
"description": "POST http://localhost:3000/auditlog/viewer/v1/project/02211171900c4172b4a80d23855961c5/eitapi_token",
|
||||
"source_ip": "1.1.0.180"
|
||||
}
|
||||
```
|
@ -0,0 +1,86 @@
|
||||
# Display Templates
|
||||
|
||||
Display templates is an important part of controlling how the events are rendered in the browser, exports or over any other stream.
|
||||
|
||||
A display template has the following components:
|
||||
|
||||
## Definitions
|
||||
|
||||
### Name
|
||||
|
||||
The name is internal only to the admin site. This is a place for you to record what the template is attempting to do.
|
||||
|
||||
### Rules
|
||||
|
||||
The rules field is a collection of rules that will be evaluated by the Retraced rules engine to determine if this template shoud be applied to the event. We'll cover that in detail shortly. But the idea is that you can have multiple rules, and the first one that matches will control how the event is rendered.
|
||||
|
||||
### Template
|
||||
|
||||
A handlebars-enabled, markdown rendered display template to use when the rules evaluate to true for a particular event. This ultimately is the text that you want to show for the matching events.
|
||||
|
||||
## Rules
|
||||
|
||||
Rules are processed against the event object. The best example is with actual data: you can click the Raw object in the admin site and see any actual event object. This is the exact context that is sent into the rule engine.
|
||||
|
||||
Rules are expressed as an array of comparators. When the _value_ of the _path_ matches the _comparator_, the rule evaluates to true and the template is applied. Retraced supports a large number of comparators, a [full list of comparators is available](/docs/retraced/advanced/template-comparators).
|
||||
|
||||
### Examples
|
||||
|
||||
This rule matches when the `action` is set to the string "document.edit":
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"comparator": "is",
|
||||
"path": "action",
|
||||
"value": "document.edit"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
This rule matches when the `action` is set to the string "document.edit" AND the type of the document is set to "spreadsheet":
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"comparator": "is",
|
||||
"path": "action",
|
||||
"value": "document.edit"
|
||||
},
|
||||
{
|
||||
"comparator": "is",
|
||||
"path": "target.type",
|
||||
"value": "spreadsheet"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Templates
|
||||
|
||||
Templates are a handlebars string that will be used to display the event. The context of the handlebars engine is the event object, and the output is a markdown string.
|
||||
|
||||
### Examples
|
||||
|
||||
Partial Event:
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "document.create",
|
||||
"actor": {
|
||||
"name": "Dr. Evil"
|
||||
},
|
||||
"target": {
|
||||
"type": "spreadsheet",
|
||||
"name": "Master Plan For World Domination.xlsx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Template:
|
||||
|
||||
```
|
||||
**{{ actor.name }}** created the document **{{ target.name }}**
|
||||
```
|
||||
|
||||
Result:
|
||||
**Dr. Evil** created the document **Master Plan For World Domination**
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Retraced Advanced Concepts
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
# Advanced Concepts
|
||||
|
||||
Once you've started sending events into Retraced, it's time to explore some of the advanced functionality.
|
||||
|
||||
- [Display templates](/docs/retraced/advanced/display-templates)
|
||||
- [Template Comparators](/docs/retraced/advanced/template-comparators)
|
||||
<!-- - [SSH Event Streaming](/docs/retraced/advanced/ssh-streaming) -->
|
||||
- [Tracking Application Versions](/docs/retraced/advanced/tracking-application-versions)
|
||||
- [Automated Audit Events](/docs/retraced/advanced/automated-audit-events)
|
@ -0,0 +1,31 @@
|
||||
# SSH Event Streaming
|
||||
|
||||
SSH Event Streaming allows Enterprise API users to stream events as they occur over ssh using an Enterprise API Token.
|
||||
|
||||
## Usage
|
||||
|
||||
To use the SSH event streaming feature, you'll need to start by getting an
|
||||
[Enterprise API token](/docs/retraced/apis/enterprise-api#getting-an-enterprise-api-token).
|
||||
|
||||
To open a stream, connect to `tail.retraced.io` using your Enterprise API token as
|
||||
the username:
|
||||
|
||||
```
|
||||
ssh aeb1c315b9a8ed11a3f998d8e8ff@tail.retraced.io
|
||||
```
|
||||
|
||||
Once the connection is open, CSV events will begin to stream through stdout,
|
||||
and can be piped to a file or other event ingest system.
|
||||
|
||||
The same token can be used for multiple concurrent streaming sessions, all sessions
|
||||
will receive every event that occurs while they are active.
|
||||
|
||||
## Parameters
|
||||
|
||||
The streaming APIs support a few parameters that can control the format of events.
|
||||
The default output format is CSV, but JSON is also supported via the
|
||||
`format` parameter
|
||||
|
||||
```sh
|
||||
ssh aeb1c315b9a8ed11a3f998d8e8ff?format=json@tail.retraced.io
|
||||
```
|
@ -0,0 +1,19 @@
|
||||
# Template Comparators
|
||||
|
||||
The following values are acceptable for "comparator" field in rules in the Retraced rules engine:
|
||||
|
||||
| Comparator | Desscription |
|
||||
| --- | --- |
|
||||
| `eq` | Matches when the `value` is equal to the event object data at `path`. This compares values only and doesn't compare types. |
|
||||
| `is` | The same as `eq` but it also compares types of objects. |
|
||||
| `neq` | Matches when the `value` is not equal to the event object data at `path`. This compares values only and doesn't compare types. This is the inverse of `eq`. |
|
||||
| `not` | The same as `neq` but it also compares types of objects. This is the inverse of `is`. |
|
||||
| `lt` | Matches when the `value` is less than the event object data at `path`. |
|
||||
| `lte` | Matches when the `value` is less than or equal to the event object data at `path`. |
|
||||
| `gt` | Matches when the `value` is greater than the event object data at `path`. |
|
||||
| `gte` | Matches when the `value` is greater than or equal to the event object data at `path`. |
|
||||
| `exists` | Matches when the `value` key exists and is not null on the event object data. |
|
||||
| `nexists` | Matches when the `value` key does not exists or is null on the event object data. |
|
||||
| `contains` | Matches when the event object data at `path` contains `value`. |
|
||||
| `ncontains` | Matches when the event object data at `path` does not contain `value`. |
|
||||
| `matches` | This rule is a raw regex rule. When the `value` is interpreted as a regular expression and applied to the event object data at `path`, returns the regex match value. |
|
@ -0,0 +1,89 @@
|
||||
# Tracking Event Publisher Versions
|
||||
|
||||
When sending events to Retraced, consumers of the [Publisher API](/docs/retraced/apis/publisher-api)
|
||||
may send event metadata like the name and version of the vendor component that is
|
||||
sending the events. A minimal event payload that includes this metadata might look like
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "user.login",
|
||||
"crud": "c",
|
||||
"group": {
|
||||
"id": "7890123",
|
||||
"name": "some.customer"
|
||||
},
|
||||
"actor": {
|
||||
"id": "123456",
|
||||
"name": "user@example.com"
|
||||
},
|
||||
"component": "authentication-api",
|
||||
"version": "ae242df"
|
||||
}
|
||||
```
|
||||
|
||||
Where `component` describes a single versioned piece of a architecture like `authentication-api`
|
||||
or `spreadsheet-processor` and `version` is usually one of
|
||||
|
||||
- A git SHA of the component's source code as in `ae242df`
|
||||
- A semantic version for the component as in `1.0.3`
|
||||
- A build number of the component as in `129`
|
||||
|
||||
Sending this information to Retraced will allow Retraced to give better
|
||||
guarantees about time windows during which an event **did not** occur.
|
||||
|
||||
## Example
|
||||
|
||||
To better understand how this works, consider the following stream of events,
|
||||
in which the `password.change` action at 12:35 is the very first `password.change`
|
||||
event seen in Retraced, because a recent new release of the vendor app is the first
|
||||
to start tracking `password.change` events.
|
||||
|
||||
| action | received |
|
||||
| ----------------- | ------------------- |
|
||||
| `email.change` | 2017-01-01 11:14:00 |
|
||||
| `user.login` | 2017-01-01 11:30:00 |
|
||||
| `email.change` | 2017-01-01 12:01:00 |
|
||||
| `user.login` | 2017-01-01 12:12:00 |
|
||||
| `password.change` | 2017-01-01 12:35:00 |
|
||||
| `user.login` | 2017-01-01 12:49:00 |
|
||||
| `password.change` | 2017-01-01 12:52:00 |
|
||||
|
||||
Without any info about app versions, we can still say for certain that
|
||||
|
||||
- no `password.change` events occured between 12:35 and 12:52.
|
||||
|
||||
We cannot say anything about whether or not any `password.change` events
|
||||
occurred before 12:35, because we have to assume that the vendor application
|
||||
was not publishing these events until we see the first one at 12:35.
|
||||
|
||||
| action | received | component | version |
|
||||
| ----------------- | ------------------- | -------------------- | --------- |
|
||||
| `email.change` | 2017-01-01 11:14:00 | `authentication-api` | `aeb22f1` |
|
||||
| `user.login` | 2017-01-01 11:30:00 | `authentication-api` | `aeb22f1` |
|
||||
| `email.change` | 2017-01-01 12:01:00 | `authentication-api` | `fd02eed` |
|
||||
| `user.login` | 2017-01-01 12:12:00 | `authentication-api` | `fd02eed` |
|
||||
| `password.change` | 2017-01-01 12:35:00 | `authentication-api` | `fd02eed` |
|
||||
| `user.login` | 2017-01-01 12:49:00 | `authentication-api` | `fd02eed` |
|
||||
| `password.change` | 2017-01-01 12:52:00 | `authentication-api` | `493ef1d` |
|
||||
|
||||
Since we know the version of the component sending each event, we can know for sure
|
||||
that the app version that sends `password.change` events was sending `email.change` events as
|
||||
early as 12:01. In addition to what we knew before, that
|
||||
|
||||
- no `password.change` events occured between 12:35 and 12:52
|
||||
|
||||
we now can also guarantee that
|
||||
|
||||
- no `password.change` events occurred between 12:01 and 12:35.
|
||||
|
||||
Note: Being able to make these guarantees relies on an assumption that application
|
||||
versions change at the same time, and that there are never multiple versions of
|
||||
a single component running in parallel for significant periods of time. If
|
||||
Publisher API consumers rely on canary deploys or staged rollouts over several days,
|
||||
then component names will need to be rotated during the rollout.
|
||||
|
||||
## Using SDKs
|
||||
|
||||
If you are using one of the official [Retraced SDKs](/docs/retraced/sdks/available-sdks),
|
||||
you can provide the `version` and `component` fields when the client is initialized,
|
||||
and they will be sent for every event.
|
@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Admin API
|
||||
sidebar_label: Admin API
|
||||
description: Admin API
|
||||
---
|
||||
|
||||
# Admin API
|
||||
|
||||
### [Swagger JSON](http://localhost:3000/auditlog/admin/v1/swagger.json) | [API Console](https://retraced.readme.io/v1.0/reference)
|
||||
|
||||
## Authentication
|
||||
|
||||
The Admin API expects a base64-encoded hmac-signed [JSON Web Token](https://tools.ietf.org/html/rfc7519) in an `Authorization` header:
|
||||
|
||||
```
|
||||
Authorization: WU9VUl9TSUdORURfSldUX1RPS0VOX18K...
|
||||
```
|
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Enterprise API
|
||||
sidebar_label: Enterprise API
|
||||
description: Enterprise API
|
||||
---
|
||||
|
||||
# Enterprise API
|
||||
|
||||
### [Swagger JSON](http://localhost:3000/auditlog/enterprise/v1/swagger.json) | [API Console](https://retraced.readme.io/v1.0/reference)
|
||||
|
||||
## Overview
|
||||
|
||||
The Enterprise API is the API that the end customer (the enterprise IT administrator) will consume to pull their organization events and ingest it into their own internal systems.
|
||||
|
||||
## Authentication
|
||||
|
||||
The Enterprise API endpoints expect the token to be provided in a header of the form
|
||||
|
||||
```
|
||||
Authorization: token=YOUR_ENTERPRISE_TOKEN
|
||||
```
|
||||
|
||||
## Getting an Enterprise API Token
|
||||
|
||||
There are currently two ways to manage Enterprise API tokens.
|
||||
|
||||
- Most often, end customers create and manage Enterprise IT tokens using the UI in the [Embedded Viewer](/docs/retraced/getting-started/embedded-viewer)
|
||||
- There are also endpoints in the [Publisher API](/docs/retraced/apis/publisher-api) that
|
||||
allow a vendor to create, edit, and delete Enterprise API tokens
|
||||
|
||||
Note that to allow end customers to manage Enterprise API tokens in the embedded viewer,
|
||||
the `is_admin` query parameter must be set to `true` when [requesting a token to initialize the embedded viewer](https://retraced.readme.io/reference#publisherv1projectprojectidviewertoken)
|
@ -0,0 +1,803 @@
|
||||
# GraphQL Endpoint
|
||||
|
||||
The recommended way to search events using an API is to POST your query and variables to the appropriate Retraced GraphQL endpoint.
|
||||
|
||||
| API | Endpoint |
|
||||
| ---------- | ----------------------------------------------------------------------------------------------- |
|
||||
| Publisher | http://localhost:3000/auditlog/publisher/v1/project/{projectId}/graphql |
|
||||
| Admin | http://localhost:3000/auditlog/admin/v1/project/{projectId}/environment/{environmentId}/graphql |
|
||||
| Enterprise | http://localhost:3000/auditlog/enterprise/v1/graphql |
|
||||
| Viewer | http://localhost:3000/auditlog/viewer/v1/graphql |
|
||||
|
||||
## Search
|
||||
|
||||
The query root provides a search method. A fully-formed query for a subset of event fields would look like this:
|
||||
|
||||
```
|
||||
{
|
||||
search(query:"action:user.login location:Germany", last:50, before:"opaquecursor") {
|
||||
totalCount
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
}
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
action
|
||||
actor {
|
||||
name
|
||||
}
|
||||
created
|
||||
country
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Variables
|
||||
|
||||
Use `query`, `last`, and `before` variables to enable reuse of your query templates. If you define a parameterized query like this...
|
||||
|
||||
```
|
||||
const searchQuery = `query Search($query: String!, $last: Int, $before: String) {
|
||||
search(query:"action:user.login location:Germany", last:50, before:"opaquecursor") {
|
||||
totalCount
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
}
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
action
|
||||
actor {
|
||||
name
|
||||
}
|
||||
created
|
||||
country
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
```
|
||||
|
||||
... then you can execute searches like this:
|
||||
|
||||
```
|
||||
const vars = {
|
||||
query: "action:user.login location:German",
|
||||
last: 50,
|
||||
before: "opaquecursor",
|
||||
};
|
||||
const res = fetch("http://localhost:3000/auditlog/publisher/v1/project/3hf140713bn302/graphql", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Token token=2ba3059ad7f14071b9befb2a7a2e195e",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: searchQuery,
|
||||
variables: vars,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
# Schema Types
|
||||
|
||||
<details>
|
||||
<summary><strong>Table of Contents</strong></summary>
|
||||
|
||||
- [GraphQL Endpoint](#graphql-endpoint)
|
||||
- [Search](#search)
|
||||
- [Variables](#variables)
|
||||
- [Schema Types](#schema-types)
|
||||
- [Query](#query)
|
||||
- [Objects](#objects)
|
||||
- [Action](#action)
|
||||
- [Actor](#actor)
|
||||
- [Display](#display)
|
||||
- [Event](#event)
|
||||
- [EventEdge](#eventedge)
|
||||
- [EventsConnection](#eventsconnection)
|
||||
- [Field](#field)
|
||||
- [Group](#group)
|
||||
- [PageInfo](#pageinfo)
|
||||
- [Target](#target)
|
||||
- [Enums](#enums)
|
||||
- [CRUD](#crud)
|
||||
- [Scalars](#scalars)
|
||||
- [Boolean](#boolean)
|
||||
- [ID](#id)
|
||||
- [Int](#int)
|
||||
- [String](#string)
|
||||
- [Interfaces](#interfaces)
|
||||
|
||||
</details>
|
||||
|
||||
## Query
|
||||
|
||||
The root query object of the Retraced GraphQL interface.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>search</strong></td>
|
||||
<td valign="top"><a href="#eventsconnection">EventsConnection</a></td>
|
||||
<td>
|
||||
|
||||
Run an advanced search for events.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="right" valign="top">query</td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The <a href="/docs/retraced/getting-started/searching-for-events/#structured-advanced-search">structured search operators</a> used to filter events.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="right" valign="top">first</td>
|
||||
<td valign="top"><a href="#int">Int</a></td>
|
||||
<td>
|
||||
|
||||
The limit of events to return, sorted from oldest to newest. It can optionally be used with the <code>after</code> argument.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="right" valign="top">after</td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
A cursor returned from a previous query.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="right" valign="top">last</td>
|
||||
<td valign="top"><a href="#int">Int</a></td>
|
||||
<td>
|
||||
|
||||
The limit of events to return, sorted from newest to oldest. It can optionally be used with the <code>before</code> argument.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="right" valign="top">before</td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
A cursor returned from a previous query.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Objects
|
||||
|
||||
### Action
|
||||
|
||||
An action.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>action</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The action field of an event such as "user.login".
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### Actor
|
||||
|
||||
The agent who performed an event.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>id</strong></td>
|
||||
<td valign="top"><a href="#id">ID</a></td>
|
||||
<td>
|
||||
|
||||
A unique id representing this actor.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>name</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The name of this actor.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>href</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The URL associated with this actor.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>fields</strong></td>
|
||||
<td valign="top">[<a href="#field">Field</a>]</td>
|
||||
<td>
|
||||
|
||||
The set of fields associated with this actor.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### Display
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>markdown</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### Event
|
||||
|
||||
A single record in an audit log.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>id</strong></td>
|
||||
<td valign="top"><a href="#id">ID</a></td>
|
||||
<td>
|
||||
|
||||
A unique id representing this event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>action</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The type of action that was taken to generate this event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>description</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The description of the event that was taken.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>group</strong></td>
|
||||
<td valign="top"><a href="#group">Group</a></td>
|
||||
<td>
|
||||
|
||||
The group associated with this event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>actor</strong></td>
|
||||
<td valign="top"><a href="#actor">Actor</a></td>
|
||||
<td>
|
||||
|
||||
The actor associated with this event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>target</strong></td>
|
||||
<td valign="top"><a href="#target">Target</a></td>
|
||||
<td>
|
||||
|
||||
The target associated with this event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>crud</strong></td>
|
||||
<td valign="top"><a href="#crud">CRUD</a></td>
|
||||
<td>
|
||||
|
||||
The classification of this event as create, read, update, or delete.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>display</strong></td>
|
||||
<td valign="top"><a href="#display">Display</a></td>
|
||||
<td>
|
||||
|
||||
The display text for this event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>received</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The time that the Retraced API received this event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>created</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The time that this event was reported as performed.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>canonical_time</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The created time if specified; else the received time.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>is_failure</strong></td>
|
||||
<td valign="top"><a href="#boolean">Boolean</a></td>
|
||||
<td>
|
||||
|
||||
Set to true if the event represents a failed use of permissions.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>is_anonymous</strong></td>
|
||||
<td valign="top"><a href="#boolean">Boolean</a></td>
|
||||
<td>
|
||||
|
||||
Set to true if the user was not logged in when performing this action.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>source_ip</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The IP address of the actor when the action was performed.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>country</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The country that the actor was in when the action was performed.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>loc_subdiv1</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The large area of the country the actor was in when the action was performed (State).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>loc_subdiv2</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The granular area of the country the actor was in when the action was performed (City).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>component</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
An identifier for the vendor app component that sent the event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>version</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
An identifier for the version of the vendor app that sent the event, usually a git SHA
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>fields</strong></td>
|
||||
<td valign="top">[<a href="#field">Field</a>]</td>
|
||||
<td>
|
||||
|
||||
The set of fields associated with this event.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>raw</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The raw event sent to the Retraced API.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### EventEdge
|
||||
|
||||
The event and cursor for a single result.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>node</strong></td>
|
||||
<td valign="top"><a href="#event">Event</a></td>
|
||||
<td>
|
||||
|
||||
The event object.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>cursor</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
An opaque cursor for paginating from this point in the search results. Use it as the <code>after</code> argument to paginate forward or the <code>before</code> argument to paginate backward.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### EventsConnection
|
||||
|
||||
The results of a search query.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>edges</strong></td>
|
||||
<td valign="top">[<a href="#eventedge">EventEdge</a>]</td>
|
||||
<td>
|
||||
|
||||
The events and cursors matching the query.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>pageInfo</strong></td>
|
||||
<td valign="top"><a href="#pageinfo">PageInfo</a></td>
|
||||
<td>
|
||||
|
||||
Indications that more search results are available.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>totalCount</strong></td>
|
||||
<td valign="top"><a href="#int">Int</a></td>
|
||||
<td>
|
||||
|
||||
The total number of search results matched by the query.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### Field
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>key</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The key for this field.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>value</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The value for this field.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### Group
|
||||
|
||||
The group this event is associated with.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>id</strong></td>
|
||||
<td valign="top"><a href="#id">ID</a></td>
|
||||
<td>
|
||||
|
||||
A unique id representing this group.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>name</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The name of this group.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### PageInfo
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>hasNextPage</strong></td>
|
||||
<td valign="top"><a href="#boolean">Boolean</a></td>
|
||||
<td>
|
||||
|
||||
When paging forward with <code>first</code>, indicates more results are available.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>hasPreviousPage</strong></td>
|
||||
<td valign="top"><a href="#boolean">Boolean</a></td>
|
||||
<td>
|
||||
|
||||
When paging backward with <code>last</code>, indicates more results are available.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### Target
|
||||
|
||||
The object an event is performed on.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Field</th>
|
||||
<th align="right">Argument</th>
|
||||
<th align="left">Type</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>id</strong></td>
|
||||
<td valign="top"><a href="#id">ID</a></td>
|
||||
<td>
|
||||
|
||||
A unique id representing this target.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>name</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The name of this target.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>href</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The URL associated with this target.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>type</strong></td>
|
||||
<td valign="top"><a href="#string">String</a></td>
|
||||
<td>
|
||||
|
||||
The type of this target entity.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" valign="top"><strong>fields</strong></td>
|
||||
<td valign="top">[<a href="#field">Field</a>]</td>
|
||||
<td>
|
||||
|
||||
The set of fields associated with this target.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Enums
|
||||
|
||||
### CRUD
|
||||
|
||||
Create | Read | Update | Delete
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th align="left">Value</th>
|
||||
<th align="left">Description</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top"><strong>c</strong></td>
|
||||
<td>
|
||||
|
||||
create
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><strong>r</strong></td>
|
||||
<td>
|
||||
|
||||
read
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><strong>u</strong></td>
|
||||
<td>
|
||||
|
||||
update
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><strong>d</strong></td>
|
||||
<td>
|
||||
|
||||
delete
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Scalars
|
||||
|
||||
### Boolean
|
||||
|
||||
The `Boolean` scalar type represents `true` or `false`.
|
||||
|
||||
### ID
|
||||
|
||||
The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.
|
||||
|
||||
### Int
|
||||
|
||||
The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
|
||||
|
||||
### String
|
||||
|
||||
The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
|
||||
|
||||
## Interfaces
|
@ -0,0 +1,289 @@
|
||||
# API Documentation
|
||||
Retraced API
|
||||
|
||||
## Version: 1.4.6
|
||||
|
||||
|
||||
**License:** UNLICENSED
|
||||
|
||||
### /enterprise/v1/graphql
|
||||
|
||||
#### POST
|
||||
##### Description:
|
||||
|
||||
Query events with [GraphQL](/docs/retraced/apis/admin-api)
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form Token token= ... | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 200 | OK |
|
||||
|
||||
null
|
||||
|
||||
### /enterprise/v1/search/active
|
||||
|
||||
#### POST
|
||||
##### Description:
|
||||
|
||||
Initiate an active search. An active search will maintain
|
||||
a persistent cursor that can be used at a later date to
|
||||
retrieve additional events from the search.
|
||||
|
||||
|
||||
Authenticate with an Enterprise API token.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | header of the form token= ... | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 201 | Created |
|
||||
|
||||
null
|
||||
|
||||
### /enterprise/v1/search/saved
|
||||
|
||||
#### POST
|
||||
##### Description:
|
||||
|
||||
Create a saved search.
|
||||
Saved searches have an ID that can be used to initiate an active search.
|
||||
|
||||
Authenticate with an Enterprise API token.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | header of the form token= ... | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 201 | Created |
|
||||
|
||||
null
|
||||
|
||||
### /publisher/v1/project/{projectId}/event
|
||||
|
||||
#### POST
|
||||
##### Description:
|
||||
|
||||
Create an event. Returns the id of the created event, and
|
||||
a cryptographic hash of the received event, as described [here](/docs/retraced/architecture/hashing-formula/).
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form token= ... | Yes | string |
|
||||
| projectId | path | the project id | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 201 | Created |
|
||||
|
||||
null
|
||||
|
||||
### /publisher/v1/project/{projectId}/event/bulk
|
||||
|
||||
#### POST
|
||||
##### Description:
|
||||
|
||||
Create one or more events. Returns a list of the ids of the created event and
|
||||
a cryptographic hash of each received events, as described [here](/docs/retraced/architecture/hashing-formula/).
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form token= ... | Yes | string |
|
||||
| projectId | path | the project id | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 201 | Created |
|
||||
|
||||
null
|
||||
|
||||
### /publisher/v1/project/{projectId}/viewertoken
|
||||
|
||||
#### GET
|
||||
##### Description:
|
||||
|
||||
Create a token for use with the Retraced embedded viewer as described [here](/docs/retraced/getting-started/embedded-viewer/).
|
||||
|
||||
**Note**: At least one of `group_id` or `team_id` is required.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form token= ... | Yes | string |
|
||||
| projectId | path | the project id | Yes | string |
|
||||
| actor_id | query | | Yes | string |
|
||||
| group_id | query | The group identifier. Same as `team_id`. If both are passed, `group_id` will be used. | No | string |
|
||||
| is_admin | query | Whether to display the Enterprise Settings and API Token Management. Set to `true` to show the settings. | No | string |
|
||||
| target_id | query | If passed, only events relating to this target will be returned in a viewer that uses the token created | No | string |
|
||||
| team_id | query | Same as `group_id`. If both are passed, `group_id` will be used. This field is deprecated. | No | string |
|
||||
| view_log_action | query | The action that will be logged when the token is used | No | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 201 | Created |
|
||||
|
||||
null
|
||||
|
||||
### /publisher/v1/project/{projectId}/group/{groupId}/enterprisetoken
|
||||
|
||||
#### POST
|
||||
##### Description:
|
||||
|
||||
Create a token for use with [Enterprise IT API](/docs/retraced/apis/enterprise-api/
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form token= ... | Yes | string |
|
||||
| projectId | path | the project id | Yes | string |
|
||||
| groupId | path | The group identifier. The generated token will be scoped to the specified group. | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 201 | Created |
|
||||
|
||||
null
|
||||
|
||||
#### GET
|
||||
##### Description:
|
||||
|
||||
List all [Enterprise IT API](/docs/retraced/apis/enterprise-api/) tokens.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form token= ... | Yes | string |
|
||||
| projectId | path | the project id | Yes | string |
|
||||
| groupId | path | The group identifier. | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 200 | OK |
|
||||
|
||||
null
|
||||
|
||||
### /publisher/v1/project/{projectId}/group/{groupId}/enterprisetoken/{tokenId}
|
||||
|
||||
#### GET
|
||||
##### Description:
|
||||
|
||||
Retrieve an [Enterprise IT API](/docs/retraced/apis/enterprise-api/) token.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form token= ... | Yes | string |
|
||||
| projectId | path | The project id. | Yes | string |
|
||||
| groupId | path | The group identifier. | Yes | string |
|
||||
| tokenId | path | The token id. | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 200 | OK |
|
||||
|
||||
null
|
||||
|
||||
#### PUT
|
||||
##### Description:
|
||||
|
||||
Update an [Enterprise IT API](/docs/retraced/apis/enterprise-api/) token
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form token= ... | Yes | string |
|
||||
| projectId | path | the project id | Yes | string |
|
||||
| groupId | path | The group identifier. | Yes | string |
|
||||
| tokenId | path | The token to update. | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 200 | OK |
|
||||
|
||||
null
|
||||
|
||||
#### DELETE
|
||||
##### Description:
|
||||
|
||||
Delete an [Enterprise IT API](/docs/retraced/apis/enterprise-api/) token
|
||||
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form token= ... | Yes | string |
|
||||
| projectId | path | the project id | Yes | string |
|
||||
| groupId | path | The group identifier. | Yes | string |
|
||||
| tokenId | path | The token to delete. | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 204 | Deleted |
|
||||
|
||||
null
|
||||
|
||||
### /publisher/v1/project/{projectId}/graphql
|
||||
|
||||
#### POST
|
||||
##### Description:
|
||||
|
||||
Query events with [GraphQL](/docs/retraced/apis/graphql/)
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ---- |
|
||||
| Authorization | header | auth header of the form Token token= ... | Yes | string |
|
||||
| projectId | path | the project id | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 200 | OK |
|
||||
|
||||
null
|
@ -0,0 +1,19 @@
|
||||
# Retraced APIs Overview
|
||||
|
||||
Retraced provides several APIs:
|
||||
|
||||
## Publisher API
|
||||
|
||||
the [Publisher API](/docs/retraced/apis/publisher-api) is the primary API that an application vendor will use to send events into Retraced. This is the API that the [Retraced SDKs](/docs/retraced/sdks/available-sdks) consume. When getting started, this is the first place to start. Use the Publisher API to start sending events into Retraced.
|
||||
|
||||
## Enterprise API
|
||||
|
||||
The [Enterprise API](/docs/retraced/apis/enterprise-api) is the API that the end customer (the enterprise IT administrator) will consume to pull their organization events and ingest it into their own internal systems.
|
||||
|
||||
## Admin API
|
||||
|
||||
The [Admin API](/docs/retraced/apis/admin-api) is an optional API that can be used in place of the Retraced Admin site. The Retraced Admin site uses this API. It's useful to managing your account and API tokens and pulling reports.
|
||||
|
||||
## Swagger Documentation
|
||||
|
||||
### [Retraced API Console](https://retraced.readme.io) | [Publisher API Swagger JSON](http://localhost:3000/auditlog/publisher/v1/swagger.json) | [Enterprise API Swagger JSON](http://localhost:3000/auditlog/enterprise/v1/swagger.json) | [Admin API Swagger JSON](http://localhost:3000/auditlog/admin/v1/swagger.json)
|
@ -0,0 +1,65 @@
|
||||
---
|
||||
title: Publisher API
|
||||
sidebar_label: Publisher API
|
||||
description: Publisher API
|
||||
---
|
||||
|
||||
# Publisher API
|
||||
|
||||
### [Swagger JSON](http://localhost:3000/auditlog/publisher/v1/swagger.json) | [API Console](https://retraced.readme.io/v1.0/reference)
|
||||
|
||||
The Publisher API is the API that most applications will embed into a production system. This API contains the methods necessary to send new events into Retraced, create [viewer tokens](/docs/retraced/getting-started/embedded-viewer) and to programmatically search events when the embedded viewer is not being used.
|
||||
|
||||
When possible, it's recommended to use one of the supported [SDKs](/docs/retraced/sdks/available-sdks) as these provide an easier way to get started.
|
||||
|
||||
To consume the Publisher API directly, we publish a Swagger spec that is both [documented](https://retraced.readme.io/reference) and available in a [raw json object](http://localhost:3000/auditlog/publisher/v1/swagger.json).
|
||||
The endpoints for reporting events are `/project/{project_id}/event` and `/project/{project_id}/event/bulk`. The bulk endpoint is for reporting multiple events in a single call. Clients using the bulk endpoint should expect longer response times when submitting large numbers of events.
|
||||
|
||||
## Body
|
||||
|
||||
We send an event json to `/project/{project_id}/event` API.
|
||||
|
||||
Following are the `mandatory` fields.
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "action-name",
|
||||
"crud": "c" | "r" | "u" | "d",
|
||||
"actor": {
|
||||
"id": "actor-id",
|
||||
"name": "actor-name"
|
||||
}
|
||||
```
|
||||
|
||||
In case of `/project/{project_id}/event/bulk` API we will send an array of events like below,
|
||||
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"action": "action-name",
|
||||
"crud": "c" | "r" | "u" | "d",
|
||||
"actor": {
|
||||
"id": "actor-id",
|
||||
"name": "actor-name"
|
||||
},
|
||||
},
|
||||
{
|
||||
"action": "action-name",
|
||||
"crud": "c" | "r" | "u" | "d",
|
||||
"actor": {
|
||||
"id": "actor-id",
|
||||
"name": "actor-name"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
The Publisher API endpoints expect the token to be provided in a header of the form
|
||||
|
||||
```
|
||||
Authorization: token=YOUR_PUBLISHER_TOKEN
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue