<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Ping Identity Developer Portal Blog</title><description>News, guidance, and deep dives from the teams building Ping Identity developer tools.</description><link>https://developer.pingidentity.com/</link><item><title>Hardening the handoff: a pattern for app-to-web single sign-on</title><link>https://developer.pingidentity.com/blog/hardening-the-handoff-a-pattern-for-app-to-web-single-sign-on/</link><guid isPermaLink="true">https://developer.pingidentity.com/blog/hardening-the-handoff-a-pattern-for-app-to-web-single-sign-on/</guid><description>A walkthrough of a standards-based pattern for securely transferring an OAuth session from a native mobile app to a web browser using Pushed Authorization Requests (PAR).</description><pubDate>Wed, 08 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;This post was originally published on &lt;a href=&quot;https://medium.com/@robertotto_31404/hardening-the-handoff-a-pattern-for-app-to-web-single-sign-on-6caf0c82786b&quot;&gt;Medium&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We’ve all been there, haven’t we? That shiny mobile app that you’ve just downloaded from your favourite brand, the one that’s offered you a really clean and modern sign in experience (without browser hand-offs, perhaps even using a passkey for quick login), suddenly and inexplicably spits you out into a browser view when you tap a particular button or menu item. Hybrid apps — those that combine both native and web elements — are an unavoidable reality for many organisations (and their users) as they look to balance time to market on new features with ever-stretched engineering budgets and the technical debt further down the stack that they’ve never quite managed to pay off.&lt;/p&gt;
&lt;p&gt;As identity professionals who care about that delicate balance between user experience and security, the question that comes up time and again is this: what is the best way to secure these apps? How do I ensure a slick user authentication process at the start and then safely re-use that session across all aspects of my application, when some parts of it are delivered via browser or web-view? In this article, I’ll explore the challenges that these hybrid app models present to us and propose a workable solution based on modern identity standards (with a sprinkling of identity orchestration). The solution I describe below has been built and tested using &lt;strong&gt;Ping Identity’s &lt;a href=&quot;https://docs.pingidentity.com/pingone/getting_started_with_pingone/p1_p1sso_start.html&quot;&gt;PingOne SSO&lt;/a&gt;&lt;/strong&gt; identity provider together with the &lt;a href=&quot;https://docs.pingidentity.com/davinci/davinci_landing_page.html&quot;&gt;&lt;strong&gt;PingOne DaVinci&lt;/strong&gt; identity orchestration engine&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Eager for the punchline? &lt;a href=&quot;#tldr&quot;&gt;Here’s the succinct summary&lt;/a&gt; for those on a time and attention budget!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;The session transfer problem&lt;/h2&gt;
&lt;p&gt;Before we can start to solve the challenges that we face in securing hybrid mobile applications, we should start by better defining the problem space. For the purposes of this discussion, we define a &lt;strong&gt;hybrid mobile application&lt;/strong&gt; as a native application running on a mobile device where certain portions of the application’s functionality are delivered via a web browser or web view on the device — that is to say, the app is not fully native. The exact specifics of how and when the app switches context between a native delivery versus a browser-based delivery of functionality are not important, however there are two requirements that we must fulfil, namely&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;access to the browser-based content requires an authenticated user session (presumably in the form of a browser session cookie, which is how these things have always been done)&lt;/li&gt;
&lt;li&gt;the user has already performed authentication in order to access the app itself and as such should not be prompted to re-authenticate in order to access the browser-based content.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A number of follow-on points are salient here and those who have grappled with this situation in the past are no doubt familiar with them. The most important ones are, perhaps, as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In a native application context, the authenticated user session is typically represented by an OAuth access token, issued to the application by a trusted Authorisation Server in response to a user login.&lt;/li&gt;
&lt;li&gt;There are &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc8252&quot;&gt;established best practices&lt;/a&gt; for how a native application should go about obtaining such a token by leveraging the Auth Code Flow with PKCE via the system browser. This approach is battle-hardened and peer-reviewed and should always be the first alternative considered when building a user authentication process for a native app.&lt;/li&gt;
&lt;li&gt;To directly contradict the previous point, however, many (if not most) digital product owners and UX designers find the experience trade-off unacceptable and thus strongly resist using a browser-delivered authentication ceremony within the context of a native application, preferring to use fully native SDKs to interact directly with the authentication service to obtain the necessary access token.&lt;/li&gt;
&lt;li&gt;Whichever approach is selected for initial user authentication, the basic requirement is the same in terms of providing a single-sign-on experience if the app includes hybrid web content; in order for the user to access said content without re-authentication, there needs to be a session cookie present in the browser at the time that content is requested. This is the most basic requirement (the &lt;em&gt;sine qua non&lt;/em&gt;, if you will) without which the user is guaranteed to be prompted for repeat authentication&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All this talk of cookies is possibly making you hungry by now, but we do need to explore the intricacies just a little deeper before taking a well-earned coffee break! This problem really is all about cookies, though — that much we cannot deny. One would think and would hope that the pattern of using the system browser to obtain authentication credentials from the user in the first place would create a session cookie in that browser as a serendipitous side effect (and give us a further piece of ammunition in convincing our product owner and UX colleagues to eschew a fully-native alternative). In practice, however, this approach has been shown to be non-deterministic at best, if not downright flaky, due to the somewhat arcane and seemingly ever-changing rules regarding cookie persistence and visibility across browser tabs and invocations. Without going into all of the details, I think it is sufficient to say that, based on the experiences of many doing this work in the field today, we cannot assume that a session cookie set during initial login will be available during subsequent browser-based interactions. The reasons for this are all very well-meant; examples being Apple’s &lt;a href=&quot;https://www.avenga.com/magazine/intelligent-tracking-prevention/&quot;&gt;Intelligent Tracking Prevention&lt;/a&gt; feature and Google’s equivalent Privacy Sandbox work — designed to increase user privacy. As a result, even if we are lucky enough to stumble upon a configuration on a given device that does give us the cookie visibility that we need, there is every chance that further tightening of cookie rules in the future could break our solution, leaving both product owners and (more importantly) end users furious.&lt;/p&gt;
&lt;p&gt;What we are left with is a challenge to solve, broadly defined as follows:&lt;/p&gt;
&lt;p&gt;“how, then, do we engineer a mechanism where the access token that represents the logged-in user within the native context can be used to create a browser session cookie at the point that the user needs to access web content”&lt;/p&gt;
&lt;p&gt;It goes without saying that any such mechanism MUST be secure and avoid exposing us and our users to malicious theft of tokens, user sessions and the applications and API’s that these protect.&lt;/p&gt;
&lt;h2&gt;A standards-based pattern for secure session transfer&lt;/h2&gt;
&lt;p&gt;We know that we need a mechanism whereby we can take the app’s representation of an authenticated user session, the OAuth access token, and turn this into an authenticated session in a web browser, in the form of a session cookie. OAuth does not provide a standardised pattern or grant type that we can use to solve this problem and as a result a number of approaches have emerged, many of which fall down on either user experience or security, and sometimes both.&lt;/p&gt;
&lt;p&gt;A naive approach to the problem would be to launch a new OAuth authorisation request in the browser via the Auth Code flow, and simply pass the app’s access token directly to the Authorisation Server as a custom URL parameter. This does imply that whatever OAuth Server implementation is in use must provide the capability to extract the access token from the query string, validate it and create a web session cookie for the subject of the token. While not many implementations that I’ve encountered will provide this sort of “access-token-to-web-session” mechanism out of the box, most will offer some sort of customisation capability, via plug-in or extension script that will allow such a mechanism to be built.&lt;/p&gt;
&lt;p&gt;I would advise against this approach for a number of reasons, with the most critical being the security risk that it carries.&lt;/p&gt;
&lt;p&gt;We must remember, at all times, the inherent security challenge implied by the Bearer Token model, where simple possession of an access token grants whoever holds the token full power to use it. We should assume that any access token issued to a native application client would be a powerful artefact indeed and allow a malicious actor the ability to invoke any API on the application back-end should they manage to obtain it. &lt;strong&gt;Adding such a dangerous object to a URL query string and sending it out “into the wild” where it could almost trivially be intercepted is not the solution we seek.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The alternative approach that I recommend is to use a relatively-recent addition to the OAuth family of standards to achieve the same outcome in a way that provides better protection of the access token during the session transfer process, namely OAuth 2.0 Pushed Authorization Requests (or PAR), described in &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc9126&quot;&gt;RFC 9126&lt;/a&gt;. To set the scene, let’s look at the abstract of the document that describes the approach:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“This document defines the pushed authorization request (PAR) endpoint, which allows clients to push the payload of an OAuth 2.0 authorization request to the authorization server via a direct request and provides them with a request URI that is used as reference to the data in a subsequent call to the authorization endpoint.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To paraphrase and simplify, PAR allows us to provide our sensitive access token directly to the Authorisation Server via a direct HTTPS Post from our native app code, rather than including it as an insecure query string parameter in the browser. This separation of data payloads between the “back channel” (direct POST) and the “front channel” (browser GET) significantly improves the security baseline of what we need to achieve and provides solid scaffolding for the further work we need to do.&lt;/p&gt;
&lt;p&gt;An additional advantage to the approach is that PAR gives us a ready-made query string parameter, in the form of the returned &lt;em&gt;request_uri&lt;/em&gt;, that is guaranteed to be single-use and short-lived, thus reducing the very large attack surface that the alternative approach inherently creates.&lt;/p&gt;
&lt;p&gt;I mentioned further work above, and it is important to realise that while PAR does provide a great starting point, it is not the complete solution to this challenge by itself. There is more to be done both in terms of user experience and also security, which we’ll explore in the next section. For now, though, let’s describe the “bones” of the approach here, in the form of a worked example&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Alice opens the Acme Inc native application and clicks the “Login” button. She is authenticated via a native authentication experience (no browser pop-up) that results in a valid OAuth access token being sent to the app. The app responsibly and securely stores this access token on her behalf.&lt;/li&gt;
&lt;li&gt;Alice clicks the “Manage My Profile” button in the app. Acme Inc delivers profile management via an embedded browser view within the app, and the web backend that serves this content requires a session cookie in order to identify Alice and link her to the correct profile.&lt;/li&gt;
&lt;li&gt;When Alice clicks the button, native app code retrieves her access token and initiates a secure POST to the Acme Inc Authorisation Server’s PAR Endpoint. The post body includes access token as a custom parameter, in addition to client_id, scope and all the other required OAuth parameters. In accordance with the PAR standard, the Authorisation server returns a response including a &lt;em&gt;request_uri&lt;/em&gt;, a single use value that acts as a reference to the request data that has been provided.&lt;/li&gt;
&lt;li&gt;The native app code now opens a browser window, passing in the URL of the Acme Inc Authorisation Server’s authentication endpoint, with the &lt;em&gt;request_uri&lt;/em&gt; from the previous step as a parameter. The Authorisation Server uses identity orchestration to validate the provided access token and create a web session for Alice, before redirecting her to the profile management application, where the browser cookie now ensures a single-sign-on experience&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The informed reader will, of course, have many remaining questions based on the above explanation. Let’s address them now.&lt;/p&gt;
&lt;h2&gt;Enabling secure session transfer on top of PAR&lt;/h2&gt;
&lt;p&gt;Native applications are public clients from an OAuth point of view. Put another way using language extracted directly from &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc6749&quot;&gt;RFC6749&lt;/a&gt;, &lt;em&gt;“it is assumed that any client authentication credentials included in the application can be extracted”&lt;/em&gt;. The implications of this reality are far reaching and many of them beyond the scope of this discussion, but it matters here because it means we cannot use a confidential client (with a client secret) to kick off our PAR request from inside the app.&lt;/p&gt;
&lt;p&gt;It is important to realise here that we are not using PAR for its ability to complete an end-to-end flow, that ends with a redirection and ultimate token issuance to the same OAuth client that initiated the request. We are rather using PAR as a way to initiate a browser flow and then build on the side effect of the session cookie that is created. This means that we do not, in fact, want to ever complete the flow that we start via PAR. We only want to go as far as creating a session cookie before we break out and redirect the user to the actual application, which will start its own Auth Code flow from scratch, using its own client_id, redirect_uri, PKCE enforcement, etc.&lt;/p&gt;
&lt;p&gt;The combination of the two factors above suggests that we should configure and use a specific OAuth Client as a sort of session transfer proxy — that is, a completely new client unrelated to either the native app that starts the transfer or the web app that ultimately benefits. We should take as many precautions as we can to lock down this session transfer client such that it can only be used for a single purpose, but also we should be sure not to add any configurations to our existing clients that could weaken their existing security posture.&lt;/p&gt;
&lt;p&gt;Let’s describe the flow again, adding the additional details that we have described above.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Alice clicks the “Manage my profile” button in the app. The app code starts the PAR process using the client_id of the dedicated Session Transfer Client. It includes a scope such as “session_transfer” in the request, and generates a PKCE Code Challenge that it includes with the request. Note that the corresponding Code Verifier can be discarded at this point since this flow is not intended to ever result in an access token issuance.&lt;/li&gt;
&lt;li&gt;The app code includes three other pieces of information (at minimum). These are the access token that it already holds for the user, the IP address that it is using, and the URL of the profile management application.&lt;/li&gt;
&lt;li&gt;It sends the PAR request to the authorisation server and obtains a response that contains a request_uri, which it appends to the AS’s authorization endpoint URL before opening a browser tab to initiate the front-channel flow.&lt;/li&gt;
&lt;li&gt;When the front-channel request hits the Authorisation Server, the request is validated (to ensure it has not expired or already been used) before being handed to the identity orchestration engine for further processing.&lt;/li&gt;
&lt;li&gt;The orchestration engine (as above, I have tested this with PingOne DaVinci, mileage may vary if using a different platform) must introspect or validate the provided access token to ensure that it is valid, has not expired and was indeed issued to the expected client (the mobile app). It should also compare the IP address provided as part of the PAR request to the IP address passed via the current HTTP request, to ensure that the backend and frontend requests come from the same place. Further checks can be implemented using orchestration logic as required.&lt;/li&gt;
&lt;li&gt;Should the above checks succeed, the orchestration engine extracts the “sub” claim from the access token to determine the appropriate user, and sets a session cookie in the browser for that same user.&lt;/li&gt;
&lt;li&gt;At this point, the orchestration logic simply redirects the browser to the URL of the profile management application (the same URL that was provided via the PAR back-channel initiation in step 3). This is the step that interrupts the flow started by the Session Transfer Client and ensure that no auth code or access token is ever issued.&lt;/li&gt;
&lt;li&gt;The profile management application now receives the browser redirect and is responsible for initiating its own OAuth/OpenID Connect Auth Code flow, just as it would had a browser opened the app URL directly. It should generate its own redirect to the AS, including its own client_id and redirect_uri, its own appropriate scopes and its own PKCE Code Challenge. The AS will start a user authentication process that should complete with no further user interaction required, based on the presence of the session cookie set in step 6.&lt;/li&gt;
&lt;li&gt;The browser is thus redirected back to the profile management application with everything that is needed to display logged-in user content.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;My good friend and proof-reader &lt;a href=&quot;https://medium.com/@gransomeuk&quot;&gt;Gransomeuk&lt;/a&gt; pointed out that some folks will just want the take away, rather than the full three course meal. With his help, here’s the summary, with a nifty sequence diagram to match.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Phase 1 (Back-Channel):&lt;/strong&gt; The mobile app passes the highly sensitive access token directly to the Authorization Server over a secure connection (POST). In return, it gets a short-lived reference string (&lt;code&gt;request_uri&lt;/code&gt;). This solves the problem of putting the Access Token in a visible URL query string.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 2 (Front-Channel):&lt;/strong&gt; The app opens the browser using only the reference string. The Identity Orchestration engine (e.g., PingOne DaVinci) verifies that the person in the browser is the same person who holds the app token (by checking IP addresses, etc) and drops a session cookie in the browser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 3 (SSO):&lt;/strong&gt; The browser is redirected to the target Web Application. Because the cookie now exists, the Web App can sign the user in automatically via standard OpenID Connect without asking the user to type in a password again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;“Next time on…”&lt;/h2&gt;
&lt;p&gt;In the interests of keeping things digestible, I will publish two follow up articles in the coming weeks.&lt;/p&gt;
&lt;p&gt;The first will explore the technical implementation of this pattern end-to-end, using PingOne SSO and PingOne DaVinci, together with a simple Android application to show it all working.&lt;/p&gt;
&lt;p&gt;The second will dive a little deeper into some of the security implications of this approach, highlight the advantages, point out a number of inherent drawbacks and also suggest further steps that can be taken to harden the implementation.&lt;/p&gt;
&lt;h2&gt;References and further reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc8252&quot;&gt;RFC 8252 — OAuth 2.0 for Native Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.researchgate.net/publication/363052475_COOKIEGRAPH_Measuring_and_Countering_First-Party_Tracking_Cookies&quot;&gt;Urban et al., “Beyond the Front Page: Measuring and Countering First-Party Cookie Tracking,” in Proc. of the 2020 World Wide Web Conference (WWW).&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc9126&quot;&gt;RFC 9126 — OAuth 2.0 Pushed Authorization Requests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>We Rebuilt the PingOne API Docs. Here’s What’s New.</title><link>https://developer.pingidentity.com/blog/we-rebuilt-the-pingone-api-docs/</link><guid isPermaLink="true">https://developer.pingidentity.com/blog/we-rebuilt-the-pingone-api-docs/</guid><description>A walkthrough of the new PingOne API docs experience, including faster navigation, in-browser request testing, and smarter search.</description><pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;If you build integrations, you probably spend a lot of time staring at API documentation. So when we decided to overhaul the PingOne API docs, our goal was simple: get out of your way and make it easier for you to actually test and write code.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.pingidentity.com/pingone-api/&quot;&gt;new site&lt;/a&gt; officially went live in early January. Here’s a quick rundown of what changed and how to use the new features.&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;It’s a lot faster and easier to navigate&lt;/h2&gt;
&lt;p&gt;The most obvious improvement is performance. The site loads faster, the pages are lighter, and the layout now matches the rest of the &lt;a href=&quot;https://docs.pingidentity.com&quot;&gt;Ping Identity documentation&lt;/a&gt; ecosystem.&lt;/p&gt;
&lt;p&gt;We also reorganized the navigation so you don’t have to dig through endless menus to find helpful information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New to PingOne?&lt;/strong&gt; We have plenty of resources to help you get up and running quickly. Jump into our &lt;a href=&quot;https://developer.pingidentity.com/pingone-api/getting-started/&quot;&gt;&lt;em&gt;Getting Started&lt;/em&gt;&lt;/a&gt; guide, explore &lt;a href=&quot;https://developer.pingidentity.com/pingone-api/foundations/&quot;&gt;&lt;em&gt;Foundations&lt;/em&gt;&lt;/a&gt;, or follow along with step-by-step tutorials in the &lt;a href=&quot;https://developer.pingidentity.com/pingone-api/workflow-library/&quot;&gt;&lt;em&gt;Use Case Library&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learn about APIs:&lt;/strong&gt; You can dive straight into the PingOne Platform &lt;a href=&quot;https://developer.pingidentity.com/pingone-api/platform/&quot;&gt;SSO&lt;/a&gt; or &lt;a href=&quot;https://developer.pingidentity.com/pingone-api/auth/&quot;&gt;Auth&lt;/a&gt; APIs to see detailed info on all endpoints, which are logically grouped by functional area.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Universal services:&lt;/strong&gt; These now have their own dedicated section, making it clearer how they fit into the wider Ping Identity portfolio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smart search:&lt;/strong&gt; If you still can’t find what you need, the search bar now uses the same AI-assisted backend as our other &lt;a href=&quot;https://docs.pingidentity.com&quot;&gt;doc sites&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Test endpoints in your browser&lt;/h2&gt;
&lt;p&gt;For every endpoint, you’ll see example requests and responses in multiple programming languages. More importantly, we completely rebuilt the &lt;strong&gt;Try Request&lt;/strong&gt; feature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Live testing:&lt;/strong&gt; Plug in your parameters, hit the button, and get real API responses back immediately.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Persistent parameters:&lt;/strong&gt; You no longer have to copy and paste the same environment or user IDs over and over. Your parameters carry over from one API call to the next. This includes access tokens, so you don’t have to constantly re-authenticate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secure local storage:&lt;/strong&gt; To keep things safe, those variables only live in your web browser’s session storage. The second you close the tab, they’re gone.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;Update your bookmarks&lt;/h2&gt;
&lt;p&gt;To keep things simple, all developer-focused content, including cloud and on-premise APIs, now lives in one place: the &lt;a href=&quot;https://developer.pingidentity.com&quot;&gt;Developer Portal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Check out the new PingOne API docs at &lt;a href=&quot;https://developer.pingidentity.com/pingone-api/&quot;&gt;&lt;strong&gt;developer.pingidentity.com/pingone-api&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Let us know what you think&lt;/h2&gt;
&lt;p&gt;This launch was a massive effort, but the work doesn’t stop here. Documentation is never really “finished.”&lt;/p&gt;
&lt;p&gt;Give the new site a spin. If you run into a weird bug, see a typo, or have any suggestions, let us know by clicking the feedback icon in the top-right corner of each page.&lt;/p&gt;
&lt;p&gt;Happy coding!&lt;/p&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Visit our new &lt;a href=&quot;https://developer.pingidentity.com/pingone-api/&quot;&gt;PingOne API documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Check out developer resources for all Ping Identity products at &lt;a href=&quot;https://developer.pingidentity.com/&quot;&gt;developer.pingidentity.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Join the discussion on the &lt;a href=&quot;https://support.pingidentity.com/s/topic/0TO1W000000Q9oRWAS/developer&quot;&gt;Ping Identity Developer Community&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Securing MCP Servers with Ping’s MCP Gateway</title><link>https://developer.pingidentity.com/blog/securing-mcp-servers-with-pings-mcp-gateway/</link><guid isPermaLink="true">https://developer.pingidentity.com/blog/securing-mcp-servers-with-pings-mcp-gateway/</guid><description>Building MCP servers that expose your business logic to AI agents? Discover how PingGateway can act as your security bouncer, handling OAuth validation, auditing, rate limiting, and policy enforcement without adding a single line of security code to your servers.</description><pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You’ve been shipping &lt;a href=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot;&gt;&lt;strong&gt;MCP servers&lt;/strong&gt;&lt;/a&gt; and each one comes with its own OAuth handler, its own scope-checking logic, its own audit hooks. Security code that should be administered centrally ends up copy-pasted across every server you build.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.pingidentity.com/pinggateway/latest/mcp/&quot;&gt;&lt;strong&gt;MCP security gateway&lt;/strong&gt;&lt;/a&gt; capabilities in &lt;a href=&quot;https://www.pingidentity.com/en/product/pinggateway.html&quot;&gt;&lt;strong&gt;PingGateway&lt;/strong&gt;&lt;/a&gt; solve this by acting as a security bouncer in front of your MCP servers. The bouncer checks credentials at the door, enforces the rules, and logs everything — so your servers never have to.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can find a deeper dive into MCP’s architecture, workflow, and security model in the &lt;a href=&quot;https://developer.pingidentity.com/identity-for-ai/agents/idai-what-is-mcp.html&quot;&gt;Ping Identity MCP documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Where PingGateway sits as your MCP security gateway&lt;/h2&gt;
&lt;p&gt;In a typical setup, &lt;strong&gt;PingGateway as an MCP security gateway&lt;/strong&gt; sits between the MCP client (the AI agent) and your MCP server.&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;What PingGateway adds for MCP servers&lt;/h2&gt;
&lt;p&gt;By fronting your MCP server, PingGateway validates that requests are syntactically correct MCP, enforces operational requirements like audit and throttling, enforces authorization of the request, and mediates security tokens before forwarding to the MCP server.&lt;/p&gt;
&lt;p&gt;Your server continues to implement tools and domain behavior; the gateway provides the surrounding security and operational controls.&lt;/p&gt;
&lt;h2&gt;What capabilities does PingGateway provide?&lt;/h2&gt;
&lt;p&gt;PingGateway extends its proven API security stack with &lt;strong&gt;MCP-aware capabilities&lt;/strong&gt; you configure once and reuse across every server:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;McpValidationFilter&lt;/strong&gt;: Validates &lt;strong&gt;Origin&lt;/strong&gt; / &lt;strong&gt;Accept&lt;/strong&gt; headers and MCP / JSON‑RPC format and populates an &lt;strong&gt;McpContext&lt;/strong&gt; so subsequent filters (throttling, policy, metrics) can inspect method and tool names.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;McpProtectionFilter&lt;/strong&gt;: Serves &lt;strong&gt;OAuth 2.0 Protected Resource Metadata&lt;/strong&gt; (&lt;code&gt;/.well-known/oauth-protected-resource/...&lt;/code&gt;) on behalf of your MCP endpoint, ensures the access token’s &lt;strong&gt;&lt;code&gt;aud&lt;/code&gt;&lt;/strong&gt; matches the configured &lt;code&gt;resourceId&lt;/code&gt; and uses PingGateway’s &lt;strong&gt;OAuth 2.0 resource server&lt;/strong&gt; capabilities to validate tokens and enforce scopes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;McpAuditFilter:&lt;/strong&gt; Emits &lt;strong&gt;MCP‑specific audit events&lt;/strong&gt; (who called which tool, where, and with what result)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP metrics&lt;/strong&gt;: Exposes &lt;strong&gt;Prometheus metrics&lt;/strong&gt; per MCP method/tool (counts, latencies, errors).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP throttling&lt;/strong&gt;: Rate limits access per route, per tool, per client or per identity.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Seeing it in action: the “unauthenticated” request&lt;/h2&gt;
&lt;p&gt;The gateway’s job is to stop what shouldn’t get through — and wave through what should. If the MCP client (AI agent) sends a request without the proper identity tokens required by the Ping Identity platform, the gateway will block it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The situation: missing authorization header.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;An AI agent sends a tool call without an &lt;code&gt;Authorization&lt;/code&gt; header:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;POST /mcp/v1/call_tool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;method&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;tools/call&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;params&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;access_customer_database&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;arguments&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;customer_id&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;12345&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;401 Unauthorized&lt;/code&gt; — rejected by PingGateway before the request ever reaches your server.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;With valid credentials, the gateway allows the request through.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The same agent retries with a valid, scoped Bearer token:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;POST&lt;/span&gt;&lt;span&gt; /mcp/v1/call_tool&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Authorization&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Bearer &amp;lt;valid-access-token&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;method&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;tools/call&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;params&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;access_customer_database&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;arguments&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;customer_id&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;12345&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;200 OK&lt;/code&gt; — PingGateway validates the token, confirms scope, logs the event, and forwards the request to your MCP server. Your server never saw the first request at all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Benefits for the MCP server developer&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MCP security shouldn’t be implemented in each MCP server’s codebase&lt;/strong&gt;&lt;br /&gt;
Without a gateway, each MCP server grows its own OAuth, scopes, auditing, throttling, and risk logic.&lt;br /&gt;
With MCP Security Gateway, a &lt;strong&gt;standard PingGateway route&lt;/strong&gt; in front of each MCP server centralizes that logic; you reuse the pattern for every new server.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comply with MCP authorization by configuration, not code&lt;/strong&gt;&lt;br /&gt;
MCP requires &lt;strong&gt;OAuth 2.0 Protected Resource Metadata&lt;/strong&gt; so agents know which AS to use and which resource they call. PingGateway serves this metadata and validates tokens according to it, so you configure security once instead of coding it per server.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gain observability “for free”&lt;/strong&gt;&lt;br /&gt;
Audit logs and metrics at the gateway show &lt;strong&gt;which tools are used, by whom, and how often&lt;/strong&gt;, without extra instrumentation in your MCP code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protect MCP servers from noisy or malicious agents&lt;/strong&gt;&lt;br /&gt;
Central throttling and policy/risk rules ensure your servers only see pre‑validated, rate‑limited, authorized requests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integrate legacy or sensitive backends cleanly&lt;/strong&gt;&lt;br /&gt;
Use &lt;strong&gt;token mediation&lt;/strong&gt; at the gateway to map agent tokens to whatever your backends expect (different scopes, JWT formats, API keys, mTLS), keeping your MCP server’s backend calls simple and aligned with existing security models.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The gateway acts as the “bouncer,” ensuring the server only spends resources processing requests that are properly formatted, authenticated, and authorized.&lt;/p&gt;
&lt;h2&gt;Get started!&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.pingidentity.com/pinggateway/latest/mcp/&quot;&gt;MCP security gateway tutorial&lt;/a&gt; walks you through the complete setup. Download the sample MCP agent and server (or bring your own), insert PingGateway in front of your MCP server, and enable MCP processing and authorization in the gateway configuration.&lt;/p&gt;
&lt;p&gt;MCP exposes your business capabilities to AI agents. &lt;a href=&quot;https://www.pingidentity.com/en/product/pinggateway.html&quot;&gt;&lt;strong&gt;PingGateway&lt;/strong&gt;&lt;/a&gt; makes sure only the right agents — with the right credentials and the right permissions — ever reach them.&lt;/p&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Get started with the &lt;a href=&quot;https://docs.pingidentity.com/pinggateway/latest/mcp/&quot;&gt;MCP security gateway tutorial&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Visit the &lt;a href=&quot;https://developer.pingidentity.com/identity-for-ai/agents/idai-what-is-mcp.html&quot;&gt;MCP documentation on the Ping Identity developer portal&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Check out developer resources for all Ping Identity products at &lt;a href=&quot;https://developer.pingidentity.com/&quot;&gt;developer.pingidentity.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Join the discussion on the &lt;a href=&quot;https://support.pingidentity.com/s/topic/0TO1W000000Q9oRWAS/developer&quot;&gt;Ping Identity Developer Community&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Introducing the PingOne Advanced Identity Cloud (AIC) MCP Server</title><link>https://developer.pingidentity.com/blog/introducing-the-aic-mcp-server/</link><guid isPermaLink="true">https://developer.pingidentity.com/blog/introducing-the-aic-mcp-server/</guid><description>Introducing the AIC MCP Server: Connect Your Identity Infrastructure to AI Agents.</description><pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Developers have already discovered that LLMs (such as Claude, Gemini, GPT, Grok, and others) accelerate workflows across coding, debugging, and operations. A real breakthrough has been the ability to create custom agents within the IDE. Now developers can write specialized agent workflows that combine reasoning, tooling, and domain logic to solve problems autonomously.&lt;/p&gt;
&lt;p&gt;To help these agents work effectively, we need a bridge between the AI and your actual services. That is where &lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt; comes in.&lt;/p&gt;
&lt;p&gt;Today, we are excited to introduce the &lt;strong&gt;AIC MCP Server&lt;/strong&gt;. This tool connects your PingOne Advanced Identity Cloud (AIC) environment directly to the AI agents you use every day in IDEs like Cursor, VS Code, and GitHub Copilot, or command-line tools like Claude Code and Gemini CLI.&lt;/p&gt;
&lt;h2&gt;What Exactly is an MCP Server?&lt;/h2&gt;
&lt;p&gt;Think of the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; as a universal remote for AI. In the past, every AI platform had to build its own unique way to talk to different databases or services. MCP changes that by creating a standard “contract.”&lt;/p&gt;
&lt;p&gt;It allows an AI agent to see a list of available tools, understand what they do, and know exactly how to call them. When you use an MCP server, you aren’t just giving an AI a window into your data; you’re giving it a specialized “hand” to perform tasks for you.&lt;/p&gt;
&lt;p&gt;You can find a more detailed look into MCP’s architecture, workflow, and security model in the &lt;a href=&quot;https://developer.pingidentity.com/identity-for-ai/agents/idai-what-is-mcp.html&quot;&gt;Ping Identity MCP documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;How the AIC MCP Server Works&lt;/h2&gt;
&lt;p&gt;PingOne Advanced Identity Cloud (AIC) is Ping Identity’s modern, single-tenant identity platform. It manages users, authentication flows, roles, policies, audit logs, and customer-facing themes. If you’re running an identity operation, AIC is where the configuration lives.&lt;/p&gt;
&lt;p&gt;The AIC MCP server is an open-source TypeScript tool, distributed through npm, which exposes 40+ tools that wrap AIC’s REST APIs and packages them as MCP-compatible functions. Instead of manually navigating the console or hand-crafting API requests, you describe what you want in natural language. Your agent translates that to the right MCP tools, the MCP server handles the API calls and authentication, and returns results that the agent can reform into natural language.&lt;/p&gt;
&lt;p&gt;Here’s the practical difference:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Task&lt;/th&gt;&lt;th&gt;Without MCP&lt;/th&gt;&lt;th&gt;With AIC MCP Server&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Find failed logins from 9 PM – 11 PM yesterday&lt;/td&gt;&lt;td&gt;20 minutes (console navigation, log filtering, export)&lt;/td&gt;&lt;td&gt;1 minute (“Show me authentication failures from 9 PM – 11 PM yesterday”)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Create a new role with specific permissions&lt;/td&gt;&lt;td&gt;15 minutes (console form, multi-step workflow)&lt;/td&gt;&lt;td&gt;2 minutes (“Create a role called product-admin with these permissions: …”)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;List all users in a specific group&lt;/td&gt;&lt;td&gt;10 minutes (API docs, construct request, parse response)&lt;/td&gt;&lt;td&gt;30 seconds (“Which users are in the engineers group?”)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Why This Matters: MCP Adoption Is Evolving&lt;/h2&gt;
&lt;p&gt;MCP has become the standard for AI-to-infrastructure integration. Popular developer tools (such as Claude Desktop, Cursor, GitHub Copilot, VS Code, Gemini CLI) all now support MCP. Developers are moving from being software engineers or technical admins to being agent orchestrators.&lt;/p&gt;
&lt;p&gt;Identity and access management (IAM) is a perfect fit for AI assistance. Configuration can be repetitive. Audits demand detailed log parsing. Bulk operations can be tedious. Configuration updates may take a while when navigating multiple screens and modals in the web console. IAM is also not an isolated capability, often connected to other systems that benefit from being managed as a group. In this way, MCP clients allow connection of multiple MCP servers from different providers to bridge multi-service, multi-product workflows. The more systems connected, the more autonomy an agent has, the more the user can delegate.&lt;/p&gt;
&lt;p&gt;For developers, this means faster operations. Less manual console navigation. Less copying and pasting IDs between tabs. Reduced context-switching.&lt;/p&gt;
&lt;h2&gt;Core Capabilities: 35+ Tools Across Five Categories&lt;/h2&gt;
&lt;p&gt;The AIC MCP server exposes 35+ tools organized into five functional areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Managed Objects:&lt;/strong&gt; Perform “search, create, and update” tasks for users, roles, groups, and organizations. (for example, &lt;em&gt;“Find all users with an @acme.com email.”&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Themes &amp;amp; Branding:&lt;/strong&gt; Update your login pages, logos, and brand colors across different regions programmatically.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logging &amp;amp; Audits:&lt;/strong&gt; Query activity logs by time, user, or error type—perfect for quick security check-ups.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secrets &amp;amp; Variables:&lt;/strong&gt; Securely manage API keys and environment variables without having to hard-code them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authentication Journeys:&lt;/strong&gt; Build and test complex login flows (journeys) and the scripts that power them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The server exposes many tools providing broad capability, with every action authenticated using OAuth 2.0 with PKCE and tied to your user identity in the audit log.&lt;/p&gt;
&lt;h2&gt;Getting Started: Hands-On Walkthrough&lt;/h2&gt;
&lt;p&gt;Getting the AIC MCP Server running takes 5 minutes. You’ll need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Sandbox or Development AIC tenant.&lt;/li&gt;
&lt;li&gt;Node.js 18+ on your machine (or Docker).&lt;/li&gt;
&lt;li&gt;An MCP-compatible AI client (Claude Desktop is recommended).&lt;/li&gt;
&lt;li&gt;5 minutes of setup time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 1: Configure Your MCP Client&lt;/h3&gt;
&lt;p&gt;Find your AIC tenant’s base URL in the console (for example, &lt;code&gt;my-tenant.forgeblocks.com&lt;/code&gt;). Then add the configuration to your MCP client’s config file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;mcpServers&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;aic-mcp-server&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;stdio&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;command&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;npx&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;args&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;&quot;-y&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;@ping-identity/aic-mcp-server&quot;&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;env&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;AIC_BASE_URL&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;your-tenant.forgeblocks.com&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;your-tenant.forgeblocks.com&lt;/code&gt; with your actual tenant URL (no &lt;code&gt;https://&lt;/code&gt; prefix).&lt;/p&gt;
&lt;h3&gt;Step 2: Authenticate&lt;/h3&gt;
&lt;p&gt;Restart your AI client. When you first use a tool, the server will:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open your browser to your AIC login screen.&lt;/li&gt;
&lt;li&gt;Ask you to log in with your AIC admin credentials as an administrator.&lt;/li&gt;
&lt;li&gt;Show you the permissions the server needs (scopes like &lt;code&gt;fr:idm:\*&lt;/code&gt;, &lt;code&gt;fr:idc:monitoring:\*&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;After you’re authenticated, securely save your token in your OS keychain (where available).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is a one-time setup for the session. The token stays in your keychain and can be reused until expiry or ephemerally if using the Docker image. Subsequent tool calls reuse the cached token, if it is still valid.&lt;/p&gt;
&lt;h3&gt;Step 3: Make Your First Tool Call&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Count all users in the system and show me the total.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Behind the scenes, your agent will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understand the available tools provided by the MCP server.&lt;/li&gt;
&lt;li&gt;Call the &lt;code&gt;listManagedObjects&lt;/code&gt; tool to discover object types.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;queryManagedObjects&lt;/code&gt; to fetch users.&lt;/li&gt;
&lt;li&gt;Return the count in plain English.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Expected response: “There are 247 users in your AIC tenant.”&lt;/p&gt;
&lt;h2&gt;Real-World Use Case: Debugging Authentication Issues&lt;/h2&gt;
&lt;p&gt;It’s 8 AM. A high-priority bug report just landed: “A recent change to the primary user authentication journey has caused failures in overnight tests.” You need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Analyze the bug&lt;/strong&gt; and map it to the existing auth journey.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provision test identities&lt;/strong&gt; that match the specific failure criteria.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trace the logs&lt;/strong&gt; to find the exact line of code or configuration causing the break.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Patch the journey&lt;/strong&gt; and verify the fix immediately.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Without the server:&lt;/strong&gt; 45 minutes of context switching (Jira, documentation, console, log aggregators, scripts).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;With the AIC MCP Server (and other MCP servers that interact with ticket systems and UX):&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;1. Analyze the Bug and Journey&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Your prompt to Claude:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Read bug report AUTH-802 and show me the current &apos;SSO-Onboarding&apos; journey configuration.  Compare with recent closed tickets that may have caused a breaking change.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;The Action:&lt;/strong&gt; Your agent fetches the ticket details using the ticket system MCP server and pulls the journey configuration. It identifies a probable failure that happens during a user lookup step from an external data source.
&lt;strong&gt;Time to insight:&lt;/strong&gt; 30 - 60 seconds.&lt;/p&gt;
&lt;h3&gt;2. Reproduce with Test Users&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Your prompt to Claude:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Create three test users: two with valid metadata in the external data source and one with invalid data to replicate the reported error.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;The Action:&lt;/strong&gt; Agent calls &lt;code&gt;createManagedObject&lt;/code&gt; and tools related to the external data source. It returns key details for fresh accounts tailored to your debugging needs.
&lt;strong&gt;Result:&lt;/strong&gt; Environment ready in 20 seconds.&lt;/p&gt;
&lt;h3&gt;3. Trace Logs &amp;amp; Identify the Root Cause&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Your prompt to Claude:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Run a test authentication for the user with invalid data. Show me the logs and highlight any stack traces.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;The Action:&lt;/strong&gt; Agent triggers a mock login and calls &lt;code&gt;queryLogs&lt;/code&gt;.
&lt;strong&gt;Result:&lt;/strong&gt; “Found an error relating to user lookup. The journey isn’t handling user lookup where there is invalid data correctly.”
&lt;strong&gt;Time to discovery:&lt;/strong&gt; 5 minutes.&lt;/p&gt;
&lt;h3&gt;4. Update &amp;amp; Re-test&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Your prompt to Claude:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Update the &apos;SSO-Onboarding&apos; journey to include appropriate error handling when user data lookups fail, then re-test with the same user.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;The Action:&lt;/strong&gt; Agent calls &lt;code&gt;saveJourney&lt;/code&gt; with the fix and re-runs the authentication trace.
&lt;strong&gt;Result:&lt;/strong&gt; “Test passed. Redirect successful. Journey updated in Dev environment.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Total time saved:&lt;/strong&gt; 30 - 45 minutes of manual work → less than 10 minutes of natural language queries. The workflow can be packaged up into an agent to save more time later. The difference compounds across your team.&lt;/p&gt;
&lt;h2&gt;Security and Caveats&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;OAuth 2.0 Authentication&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Every tool call is authenticated with your AIC credentials using OAuth 2.0 (PKCE flow). Your password is never stored. The resulting access token is saved securely in your OS keychain—the same place your browser stores credentials.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Audit Trail&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;All actions—queries, creates, updates, deletes—appear in your AIC audit log tied to your user identity and are traceable as MCP-based interactions. There’s full traceability for compliance and security reviews.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sandbox and Development Only&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Currently, the server works with Sandbox and Development AIC tenants only. Production support is on the roadmap. This ensures you can safely experiment and iterate without risk to live systems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agent Permissions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Only use the MCP server with AI agents you trust. The agent has the same permissions as your authenticated user. If you’re an AIC admin, the agent is an admin. Always review agent prompts and tool calls before deploying them to production workflows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Source&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The server is Apache 2.0 licensed and open-source on GitHub. Review the code, audit the dependencies, and contribute. The entire codebase is at &lt;a href=&quot;https://github.com/pingidentity/aic-mcp-server&quot;&gt;github.com/pingidentity/aic-mcp-server&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next Steps: Try It Today, Give us Feedback&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Run your first agent workflow.&lt;/li&gt;
&lt;li&gt;Consider your developer workflows, how can the MCP server be used to turn repetitive or menial tasks into automated, intelligent workflows?&lt;/li&gt;
&lt;li&gt;Share your use cases and workflows with the &lt;a href=&quot;https://support.pingidentity.com/s/topic/0TO1W000000Q9oRWAS/developer&quot;&gt;Ping Identity developer community&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you find issues or would like to see enhancements, &lt;a href=&quot;https://github.com/pingidentity/aic-mcp-server/issues&quot;&gt;raise an issue on the code repository&lt;/a&gt;. We’re listening!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The AIC MCP Server is in early release. Your feedback shapes what comes next!&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GitHub Repository: &lt;a href=&quot;https://github.com/pingidentity/aic-mcp-server&quot;&gt;https://github.com/pingidentity/aic-mcp-server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;NPM Package: &lt;a href=&quot;https://www.npmjs.com/package/@ping-identity/aic-mcp-server&quot;&gt;https://www.npmjs.com/package/@ping-identity/aic-mcp-server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PingOne AIC Documentation: &lt;a href=&quot;https://docs.pingidentity.com/pingoneaic/latest/&quot;&gt;https://docs.pingidentity.com/pingoneaic/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Model Context Protocol (MCP) Specification: &lt;a href=&quot;https://modelcontextprotocol.io/specification/2025-11-25&quot;&gt;https://modelcontextprotocol.io/specification/2025-11-25&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OAuth 2.0 PKCE (RFC 7636): &lt;a href=&quot;https://tools.ietf.org/html/rfc7636&quot;&gt;https://tools.ietf.org/html/rfc7636&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Introducing the PingOne MCP server</title><link>https://developer.pingidentity.com/blog/introducing-the-pingone-mcp-server/</link><guid isPermaLink="true">https://developer.pingidentity.com/blog/introducing-the-pingone-mcp-server/</guid><description>The PingOne MCP Server brings your identity infrastructure into your development workflow. Configure environments, applications, and populations without leaving your IDE.</description><pubDate>Tue, 31 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Developers building applications using PingOne eventually hit the same friction point. Application code is in the IDE, while application configuration, audit logs, policies, and user journey flows are managed in the web console.&lt;/p&gt;
&lt;p&gt;That context switch is the problem, not the task itself. Registering an application in PingOne or spinning up a new environment for development is straightforward. The cost is the frequent interruption leading to a break in flow, tab switching, and copying and pasting IDs.&lt;/p&gt;
&lt;p&gt;Although frequent switching between IDE and the web console has been well accepted over the years, the expectations of application developers is shifting. Application developers are shifting to AI tools and agentic development practices. Generative code experiences such as VS Code Copilot, Claude Desktop, Claude Code, Gemini CLI, and GPT Codex are changing the ways that developers interact with their application code, and they’re changing the way developers interact with online services.&lt;/p&gt;
&lt;p&gt;The PingOne MCP Server reduces the gap. It connects your PingOne tenant directly to MCP-compatible generative AI IDEs and CLIs. Instead of leaving your editor, you describe what you need from your application integration in natural language, and your agent handles the PingOne API calls, returns the IDs and configuration details you need, and lets you keep iterating on application code.&lt;/p&gt;
&lt;p&gt;This isn’t about replacing the PingOne console for operational work. It’s about making identity platform configuration a first-class citizen of the development cycle, available in the same context where you write code, run tests, and ship features.&lt;/p&gt;
&lt;h2&gt;What Is MCP?&lt;/h2&gt;
&lt;p&gt;System configuration living outside the development cycle isn’t unique to PingOne. But it’s a fundamental challenge in building agentic systems: how do AI agents and IDE AI chat systems connect to the external services they need to act on?&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://modelcontextprotocol.io/docs/getting-started/intro&quot;&gt;Model Context Protocol (MCP)&lt;/a&gt;, originally developed by Anthropic, provides a specification for the interactions between AI systems (the abstract world of “intent”) and today’s systems (the concrete world of deterministic input/output). Before MCP, every integration between an AI agent and an external tool required custom code—bespoke connectors, point-in-time maintenance, duplicated effort across teams. MCP standardizes the connection layer, providing a “USB style” connector interface so that any MCP-compatible client (VS Code Copilot, Claude Desktop, Cursor, and others) can discover and invoke any MCP server’s capabilities using a common protocol, without needing custom code on either side.&lt;/p&gt;
&lt;p&gt;In practical terms, an MCP server currently exposes three types of capabilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tools&lt;/strong&gt; (executable actions the agent can invoke)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resources&lt;/strong&gt; (contextual data to inform reasoning)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prompts&lt;/strong&gt; (templated workflows)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The agent discovers tools at runtime, selects what it needs, and calls them through JSON-RPC messages. Prompts and resources are loaded at the user’s request.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can find a deeper dive into MCP’s architecture, workflow, and security model in the &lt;a href=&quot;https://developer.pingidentity.com/identity-for-ai/agents/idai-what-is-mcp.html&quot;&gt;Ping Identity MCP documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;What is the PingOne MCP Server?&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server&quot;&gt;PingOne MCP Server&lt;/a&gt; implements the MCP standard for PingOne’s Management API, exposing 14 tools across 4 capability areas, and represents the start of the journey in producing useful tools to accelerate developer workflows.&lt;/p&gt;
&lt;p&gt;In practical terms: your AI agent in your IDE can now interact with your PingOne tenant the same way it interacts with your filesystem, your terminal, or your version control. It becomes part of the same conversation as your application code.&lt;/p&gt;
&lt;p&gt;The initial set of tools cover what developers need most when building on PingOne:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Applications&lt;/strong&gt;: List, retrieve, create, and update OIDC/OAuth 2.0 applications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environments&lt;/strong&gt;: List, retrieve, create, and update PingOne environments; manage services (such as MFA and DaVinci)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Populations&lt;/strong&gt;: List, retrieve, create, and update user populations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Directory&lt;/strong&gt;: Generate per-day identity trend reports.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All operations execute as the authenticated user and are logged in PingOne’s audit trail. The agent never sees your access tokens or sign-on credentials; the MCP server handles authentication entirely, returning only the data the agent needs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Missing something you need? Get in touch! Raise an &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server/issues/new&quot;&gt;enhancement request on the code repository&lt;/a&gt;. Your feedback helps drive what we do next.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Getting Started: From Zero to First Tool Call&lt;/h2&gt;
&lt;p&gt;To get started you need a PingOne account (&lt;a href=&quot;https://www.pingidentity.com/en/try-ping.html&quot;&gt;Try Ping here&lt;/a&gt;), an MCP-compatible client (VS Code with Copilot, Cursor, Claude Desktop, or similar).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For the adventurous&lt;/strong&gt;, in your favourite agent IDE, try:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Help me install and configure the PingOne MCP server from github.com/pingidentity/pingone-mcp-server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Otherwise, follow the instructions below.&lt;/p&gt;
&lt;h3&gt;1. Install the Server&lt;/h3&gt;
&lt;p&gt;The easiest path on macOS or Linux is Homebrew:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;brew&lt;/span&gt;&lt;span&gt; tap&lt;/span&gt;&lt;span&gt; pingidentity/tap&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;brew&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; pingone-mcp-server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verify:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;pingone-mcp-server&lt;/span&gt;&lt;span&gt; --version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;For Windows, the MCP server is built as an executable file, ready to download from the &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server/releases&quot;&gt;project releases&lt;/a&gt;. See the project &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server?tab=readme-ov-file#install-the-mcp-server&quot;&gt;README&lt;/a&gt; for full details for Windows installation and other options.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;2. Set Up a Worker Application in PingOne&lt;/h3&gt;
&lt;p&gt;The server needs credentials. Create a worker application in your PingOne tenant:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sign on to the PingOne Administration Console.&lt;/li&gt;
&lt;li&gt;Open the environment for your Administrator users.&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Applications&lt;/strong&gt; &amp;gt; &lt;strong&gt;Add (+)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Name it (for example, “PingOne MCP Server”) and choose type &lt;strong&gt;Worker&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Configuration&lt;/strong&gt; and configure OAuth 2.0 settings:
&lt;ul&gt;
&lt;li&gt;Set response type to &lt;strong&gt;Code&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set grant type to &lt;strong&gt;Authorization Code&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;PKCE Enforcement&lt;/strong&gt; to &lt;strong&gt;S256_REQUIRED&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Refresh Token&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Set redirect URI to &lt;code&gt;http://127.0.0.1:7464/callback&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set the Token Endpoint Authentication Method to &lt;strong&gt;None&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Save and capture your &lt;strong&gt;Environment ID&lt;/strong&gt; and &lt;strong&gt;Client ID&lt;/strong&gt; from the application details.&lt;/li&gt;
&lt;li&gt;Finally, remember to enable the MCP server application!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;Although the example here uses the ‘Authorization Code’ grant type, ‘Device Code’ is also available. You can find more details in &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server/blob/main/docs/setup-pingone-worker-application.md&quot;&gt;Setting Up PingOne Worker Applications for MCP Server&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;3. Configure Your MCP Client&lt;/h3&gt;
&lt;p&gt;Once installed, add the server to your MCP client’s configuration. For VS Code with Copilot Chat:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;servers&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;pingOne&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;type&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;stdio&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;command&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;pingone-mcp-server&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;args&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;run&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // &quot;--disable-read-only&quot; // uncomment to enable write tools&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;env&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;PINGONE_MCP_ENVIRONMENT_ID&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;your-environment-id-uuid&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;PINGONE_AUTHORIZATION_CODE_CLIENT_ID&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;your-client-id-uuid&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;PINGONE_ROOT_DOMAIN&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;pingone.com&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;If your tenant is in a different region, use &lt;em&gt;pingone.ca&lt;/em&gt;, &lt;em&gt;pingone.eu&lt;/em&gt;, &lt;em&gt;pingone.com.au&lt;/em&gt;, &lt;em&gt;pingone.sg&lt;/em&gt; or &lt;em&gt;pingone.asia&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To install to other IDEs, including Claude Code, Gemini and Cursor, refer to the project &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server&quot;&gt;README&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That’s it. On first tool use, your browser opens your PingOne administrator sign-on page. After you authenticate with your admin credentials, the server caches your token securely in your OS keychain (where available) or is cached ephemerally. Every subsequent tool call validates and reuses the same token.&lt;/p&gt;
&lt;h2&gt;Real-World Use Case: Prepare an Environment for App Development&lt;/h2&gt;
&lt;p&gt;You’re building a new application feature that requires its own isolated identity configuration: a dedicated, ephemeral sandbox environment, a test user population, and an OIDC application for the OAuth flow your code will use.&lt;/p&gt;
&lt;p&gt;Without the MCP server, you stop coding, switch to a browser, walk through the PingOne console to create the environment, toggle the services you need, create the population, register the application, copy the client ID and environment ID back into your project, and resume back.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;With the PingOne MCP Server, you stay in your IDE:&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that write tools must be enabled using &lt;code&gt;--disable-read-only&lt;/code&gt; at startup.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Step 1 — Understand what already exists:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&quot;List my PingOne sandbox environments and show me which services are enabled in each.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The agent calls &lt;code&gt;list_environments&lt;/code&gt; and returns a structured overview. You can see your existing dev and staging environments, what’s running in each, and confirm there’s no overlap with what you’re about to create.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2 — Create the new environment:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&quot;Create a new sandbox environment called &apos;feature-payments-dev&apos;.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Enable the MFA and DaVinci services.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The agent calls &lt;code&gt;create_environment&lt;/code&gt;, then &lt;code&gt;update_environment_services&lt;/code&gt; to add MFA and DaVinci, and returns the environment ID. You paste it into your &lt;code&gt;.env&lt;/code&gt; file without leaving the editor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3 — Create the test population:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&quot;Create a population called &apos;Payments Test Users&apos; in the&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;feature-payments-dev environment.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The agent calls &lt;code&gt;create_population&lt;/code&gt;. Returns the population ID. You add it to your test harness configuration inline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4 — Register the OIDC application:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&quot;Create an OIDC application in feature-payments-dev called&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&apos;Payments App&apos;. Use authorization code grant with PKCE enforced.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Redirect URI is http://localhost:3000/callback.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The agent calls &lt;code&gt;create_oidc_application&lt;/code&gt; with the correct grant type, PKCE settings, and redirect URI. It returns the client ID.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 5 — Confirm and move on:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&quot;Give me a summary of the feature-payments-dev environment:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;environment ID, enabled services, population name and ID,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;and the Payments App client ID.&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The agent returns a clean summary, and you’re ready to move on. The entire flow took less than three minutes without switching context once. All four operations are in your PingOne audit log, associated with your user identity.&lt;/p&gt;
&lt;p&gt;The process can be wrapped into a skill or an agent, and the rest of the team can benefit from the workflow.&lt;/p&gt;
&lt;h2&gt;Security Considerations&lt;/h2&gt;
&lt;p&gt;The most important thing to understand about the PingOne MCP Server’s security model: the agent is acting as you. The MCP server doesn’t have its own service account, its own permissions, or its own audit identity. When the agent calls a PingOne API through the MCP server, it calls it as your authenticated user account. Everything it does is bounded by the PingOne roles assigned to your admin account and actions are visible in the audit log, attributable to your identity.&lt;/p&gt;
&lt;p&gt;Other features include:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Production environment restrictions.&lt;/strong&gt; By default, all write actions are disabled on production environments. This is to protect against accidental or unintended configuration changes, even if your user has the ability to make changes to production configuration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Write operations require an explicit decision when starting the MCP server.&lt;/strong&gt; Running the server without &lt;code&gt;--disable-read-only&lt;/code&gt; exposes only read tools. This is to allow you to explicitly opt in to write tools on your tenant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Full audit trail.&lt;/strong&gt; Every API call from the server includes a session ID and transaction ID in the request headers. You can trace any change back to the MCP server session through PingOne’s audit log.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Preview software.&lt;/strong&gt; This is an early release. APIs and behavior may change. Use caution when using the MCP server against important environments. Found a bug? &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server/issues&quot;&gt;Open an issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open source.&lt;/strong&gt; Apache 2.0 licensed. Read the code, audit the dependencies, contribute a fix: &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server&quot;&gt;github.com/pingidentity/pingone-mcp-server&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next Steps: Try It Today, Give us Feedback&lt;/h2&gt;
&lt;p&gt;The current 14 tools cover a subset of what developers may need when developing on PingOne. But the goal is broader: PingOne configuration should be as accessible from your IDE as your database schema, your API spec, or your CI/CD pipeline. Manual steps you need to take between your code and your identity configuration is a point of friction that can be improved upon.&lt;/p&gt;
&lt;p&gt;Near-term additions include Docker support for containerized workflows and simplified installation, expanded tool coverage across more PingOne APIs, and support for upcoming MCP specification changes as the standard evolves.&lt;/p&gt;
&lt;p&gt;The roadmap is shaped by what you actually need. If there’s a specific tool or capability that would close a gap in your workflow, &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server/issues&quot;&gt;raise an enhancement request&lt;/a&gt; or start a discussion in the repository.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Get a &lt;a href=&quot;https://www.pingidentity.com/en/try-ping.html&quot;&gt;PingOne trial account&lt;/a&gt;&lt;/strong&gt; if you don’t have one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Install and follow the project &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server&quot;&gt;README&lt;/a&gt;.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Think about the identity configuration steps in your current developer workflow. Where does context-switching slow you down?&lt;/li&gt;
&lt;li&gt;Share what you build with the &lt;a href=&quot;https://support.pingidentity.com/s/topic/0TO1W000000Q9oRWAS/developer&quot;&gt;Ping Identity community&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your feedback shapes what comes next. Try it today and give us feedback on what you want to build.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PingOne MCP Server code repository: &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server&quot;&gt;https://github.com/pingidentity/pingone-mcp-server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PingOne MCP Server releases: &lt;a href=&quot;https://github.com/pingidentity/pingone-mcp-server/releases&quot;&gt;https://github.com/pingidentity/pingone-mcp-server/releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PingOne documentation: &lt;a href=&quot;https://docs.pingidentity.com/pingone/latest/&quot;&gt;https://docs.pingidentity.com/pingone/latest/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Model Context Protocol (MCP) specification: &lt;a href=&quot;https://modelcontextprotocol.io/specification/2025-11-25&quot;&gt;https://modelcontextprotocol.io/specification/2025-11-25&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PingOne Management API: &lt;a href=&quot;https://apidocs.pingidentity.com/pingone/platform/v1/api/&quot;&gt;https://apidocs.pingidentity.com/pingone/platform/v1/api/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OAuth 2.0 PKCE (RFC 7636): &lt;a href=&quot;https://tools.ietf.org/html/rfc7636&quot;&gt;https://tools.ietf.org/html/rfc7636&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Homebrew Tap: &lt;a href=&quot;https://github.com/pingidentity/homebrew-tap&quot;&gt;https://github.com/pingidentity/homebrew-tap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Rapidly Deploying PingGateway with PingOne Advanced Identity Cloud (P1AIC)</title><link>https://developer.pingidentity.com/blog/rapidly-deploying-pinggateway-with-pingone-advanced-identity-cloud-p1aic/</link><guid isPermaLink="true">https://developer.pingidentity.com/blog/rapidly-deploying-pinggateway-with-pingone-advanced-identity-cloud-p1aic/</guid><description>A step-by-step guide to rapidly deploying PingGateway in standalone mode and integrating it with PingOne Advanced Identity Cloud using CDSSO.</description><pubDate>Tue, 03 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;This post was originally published on &lt;a href=&quot;https://medium.com/@darinder.shokar/rapidly-deploying-pinggateway-with-pingone-advanced-identity-cloud-p1aic-a500d3734a63&quot;&gt;Medium&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note: This blog applies to PingGateway versions from 2025 onwards. For earlier PingGateway (IG) releases, please refer to the original blog &lt;a href=&quot;https://medium.com/@darinder.shokar/forgerock-identity-gateway-ig-integration-with-the-new-forgerock-identity-cloud-bf87b0b25a08&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Integrating applications securely and efficiently with PingOne Advanced Identity Cloud (P1AIC) is a common requirement for developers and architects exploring modern identity platforms.&lt;/p&gt;
&lt;p&gt;This article demonstrates how to deploy PingGateway in standalone mode and protect a sample application using Cross-Domain Single Sign-On (CDSSO) with P1AIC — all via a single automation script.&lt;/p&gt;
&lt;p&gt;The objective is straightforward:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Enable new users to quickly stand up PingGateway, integrate it with P1AIC, and understand how CDSSO protection works end-to-end.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This deployment is designed for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learning and enablement&lt;/li&gt;
&lt;li&gt;Proof-of-concept environments&lt;/li&gt;
&lt;li&gt;Developer experimentation&lt;/li&gt;
&lt;li&gt;Workshops and demonstrations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is not intended as production use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The repository containing all assets and the deployment script is located &lt;a href=&quot;https://github.com/forgerock-dss/PingGatewayIntegrationwithP1AIC-2025&quot;&gt;here&lt;/a&gt; on GitHub.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To get straight to deploying go here.&lt;/p&gt;
&lt;h2&gt;Scenario&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;“As a new customer, I want to understand PingGateway through hands-on experimentation — specifically how to configure it to protect an application via CDSSO with P1AIC.”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This blog walks through that exact scenario.&lt;/p&gt;
&lt;h2&gt;What the Script Deploys&lt;/h2&gt;
&lt;p&gt;The repository includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;install_ping_gateway_P1AIC.sh&lt;/code&gt; — automation script&lt;/li&gt;
&lt;li&gt;&lt;code&gt;admin.json.HTTPS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;admin.json.HTTP_ONLY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;static-resources.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cdsso-idc.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When executed, the script provisions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A PingGateway standalone instance&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A Sample Application&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Route configurations that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reverse proxy static resources&lt;/li&gt;
&lt;li&gt;Protects &lt;code&gt;/home/cdsso&lt;/code&gt; via CDSSO with P1AIC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All components are deployed on the same host for simplicity.&lt;/p&gt;
&lt;h2&gt;Architecture Overview&lt;/h2&gt;
&lt;p&gt;PingGateway runs in &lt;strong&gt;Standalone Mode&lt;/strong&gt;, meaning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It does not require deployment into a servlet container.&lt;/li&gt;
&lt;li&gt;It runs directly from the extracted ZIP.&lt;/li&gt;
&lt;li&gt;It uses Vert.x internally to provide its runtime engine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result is a lightweight, fast-starting gateway instance suitable for development and experimentation.&lt;/p&gt;
&lt;p&gt;The end-to-end flow looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User accesses protected resource via PingGateway.&lt;/li&gt;
&lt;li&gt;PingGateway checks for a valid OIDC token.&lt;/li&gt;
&lt;li&gt;If no valid token is present, the browser is redirected to P1AIC.&lt;/li&gt;
&lt;li&gt;User authenticates with P1AIC.&lt;/li&gt;
&lt;li&gt;P1AIC redirects back to PingGateway.&lt;/li&gt;
&lt;li&gt;PingGateway validates the token and grants access to the sample application.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This demonstrates CDSSO in action, and described in more details below:&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;To learn more about CDSSO check out &lt;a href=&quot;https://docs.pingidentity.com/pinggateway/latest/gateway-guide/cdsso.html&quot;&gt;this&lt;/a&gt; link&lt;/p&gt;
&lt;h2&gt;Script Execution&lt;/h2&gt;
&lt;h3&gt;Step 1 — Download Assets aond Configure Networking&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Download the ZIP from GitHub &lt;a href=&quot;https://github.com/forgerock-dss/PingGatewayIntegrationwithP1AIC-2025&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Down the PingGateway Standalone ZIP and PingGateway Sample Application JAR from &lt;a href=&quot;https://backstage.forgerock.com/downloads/browse/ig/featured&quot;&gt;here&lt;/a&gt; and place both files in the same directory as the script.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;By default PingGateway will be deployed against this host &lt;code&gt;pinggateway.test.com&lt;/code&gt; and the Sample app to &lt;code&gt;sample.test.com&lt;/code&gt;. Add both to your &lt;code&gt;/etc/hosts&lt;/code&gt; file. For example for IP 172.168.1.10 the hosts entry will look like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;172.168.1.10 pinggateway.test.com sample.test.com&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 2 — Configure the Script&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Modify lines 11–30 in the &lt;code&gt;install_ping_gateway_P1AIC.sh&lt;/code&gt; script to match your environment&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 3 — Configure P1AIC&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Create a Test User&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Log in to P1AIC.&lt;/li&gt;
&lt;li&gt;Select the appropriate realm.&lt;/li&gt;
&lt;li&gt;Navigate to Identities → Manage.&lt;/li&gt;
&lt;li&gt;Create a new user.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Create a Gateway Agent&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Navigate to Gateways and Agents.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click New Gateway/Agent.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select Identity Gateway.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter the following and hit Save:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agent ID (e.g. &lt;code&gt;pinggateway_agent_cdsso&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Password&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ensure these values match the script configuration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AGENT_ID&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AGENT_SECRET&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Configure Redirect URIs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;HTTPS:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pinggateway.test.com:9443/home/cdsso/redirect&quot;&gt;https://pinggateway.test.com:9443/home/cdsso/redirect&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;HTTP:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://pinggateway.test.com:9000/home/cdsso/redirect&quot;&gt;http://pinggateway.test.com:9000/home/cdsso/redirect&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Step 4 — Execute the Script&lt;/h3&gt;
&lt;p&gt;For P1AIC deployments, use HTTPS mode due to SameSite cookie requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run: &lt;code&gt;./install_ping_gateway_P1AIC.sh https&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For standalone PingAM deployments run &lt;code&gt;./install_ping_gateway_P1AIC.sh http&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 5 — Validate Deployment&lt;/h3&gt;
&lt;p&gt;After deployment, access:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pinggateway.test.com:9443/home/cdsso&quot;&gt;https://pinggateway.test.com:9443/home/cdsso&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You should be redirected to P1AIC for authentication. Upon successful login, the Sample Application page will be displayed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note: If you were already logged into P1AIC during setup, log out first or use a private browser window to prevent cookie conflicts.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h3&gt;Step 6— Stop/Start the&lt;/h3&gt;
&lt;p&gt;To stop/start PingGateway and the Sample App use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stop Services: &lt;code&gt;./install_ping_gateway_P1AIC.sh stop&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Start Services: &lt;code&gt;./install_ping_gateway_P1AIC.sh start&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Script Breakdown&lt;/h2&gt;
&lt;p&gt;The script performs the following high-level steps.&lt;/p&gt;
&lt;h3&gt;1. Environment Validation&lt;/h3&gt;
&lt;p&gt;The script validates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PingGateway ZIP is present&lt;/li&gt;
&lt;li&gt;Sample Application JAR is present&lt;/li&gt;
&lt;li&gt;Required commands are available (&lt;code&gt;unzip&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;The host can connect to the configured P1AIC endpoint&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Execution stops if validation fails.&lt;/p&gt;
&lt;h3&gt;2. Clean Installation Handling&lt;/h3&gt;
&lt;p&gt;If a previous installation exists:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PingGateway is stopped&lt;/li&gt;
&lt;li&gt;The sample application is stopped&lt;/li&gt;
&lt;li&gt;The installation directory is removed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This ensures clean redeployment.&lt;/p&gt;
&lt;h3&gt;3. PingGateway Deployment&lt;/h3&gt;
&lt;p&gt;The script:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extracts the PingGateway ZIP&lt;/li&gt;
&lt;li&gt;Performs a temporary start/stop cycle to initialise directories&lt;/li&gt;
&lt;li&gt;Creates required configuration folders&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PingGateway is deployed in Production Mode by default.&lt;/p&gt;
&lt;h3&gt;4. Script Execution Mode&lt;/h3&gt;
&lt;p&gt;The script supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;https mode (recommended for P1AIC)&lt;/li&gt;
&lt;li&gt;http mode (for standalone PingAM deployments)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When HTTPS mode is selected, a self-signed certificate is generated automatically.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note — Self-signed certificates are for demonstration only and should not be used in production.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;5. Sample Application Deployment&lt;/h3&gt;
&lt;p&gt;The sample application is deployed locally and started on the configured ports, providing a target application for PingGateway to protect.&lt;/p&gt;
&lt;h3&gt;6. Route Configuration&lt;/h3&gt;
&lt;p&gt;Two routes are created:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;static-resources.json&lt;/code&gt; — Allows PingGateway to proxy static resources (e.g., CSS) without authentication. This improves performance and mirrors real-world deployment patterns.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cdsso-idc.json&lt;/code&gt; — Protects the /home/cdsso context. It checks for a valid OIDC id_token, redirects unauthenticated users to P1AIC, validates tokens on return and grants access upon successful validation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This script provides a fast, repeatable way to deploy PingGateway locally and integrate it with PingOne Advanced Identity Cloud using CDSSO — all within minutes. It enables you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deploy PingGateway in standalone mode&lt;/li&gt;
&lt;li&gt;Understand how standalone runtime operates&lt;/li&gt;
&lt;li&gt;Explore CDSSO behaviour with P1AIC&lt;/li&gt;
&lt;li&gt;Observe complete end-to-end authentication flows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By simplifying setup and automating the foundational configuration, this approach accelerates learning and removes friction from experimentation. It serves as an ideal starting point for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developers building familiarity with PingGateway&lt;/li&gt;
&lt;li&gt;Architects validating integration patterns&lt;/li&gt;
&lt;li&gt;Technical enablement sessions and workshops&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most importantly, it provides a clear, structured baseline from which you can extend into more advanced routing logic, security hardening, certificate management, and production-ready deployment patterns.&lt;/p&gt;
&lt;p&gt;In short, this script turns what could be a multi-step manual configuration process into a streamlined, educational experience — helping you move from exploration to implementation with confidence.&lt;/p&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CDSSO Documentation — &lt;a href=&quot;https://docs.pingidentity.com/pinggateway/latest/aic/cdsso.html&quot;&gt;https://docs.pingidentity.com/pinggateway/latest/aic/cdsso.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PingGateway Documentation — &lt;a href=&quot;https://docs.pingidentity.com/pinggateway/latest/&quot;&gt;https://docs.pingidentity.com/pinggateway/latest/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Securing High-Risk Actions: Transactional Authorization over REST</title><link>https://developer.pingidentity.com/blog/securing-high-risk-actions-transactional-authorization-over-rest/</link><guid isPermaLink="true">https://developer.pingidentity.com/blog/securing-high-risk-actions-transactional-authorization-over-rest/</guid><description>A practical guide to securing high-risk actions with REST-based Transactional Authorization.</description><pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;This post was originally published on &lt;a href=&quot;https://medium.com/@darinder.shokar/securing-high-risk-actions-transactional-authorization-over-rest-8e3a6fbf474b&quot;&gt;Medium&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Requiring a user to explicitly authorise access to a sensitive resource every time they attempt to access it is a common security requirement. A typical example is in financial services, where initiating a payment might trigger a one-time passcode (OTP) sent to the user’s device, or a push notification requiring approval. These additional steps increase friction intentionally, ensuring the user is genuinely present and consenting before a high-risk action is allowed.&lt;/p&gt;
&lt;p&gt;In the PingOne Advanced Identity Cloud (P1AIC) and PingOne Advanced Identity Software (self-managed PingAM), this capability is known as Transactional Authorisation (TAuthZ). You can read more about it &lt;a href=&quot;https://docs.pingidentity.com/pingoneaic/latest/am-authorization/transactional-authorization.html#understand_transactional_authorization&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;The most common and recommended architecture for enabling Transactional Authorisation is to use a Policy Enforcement Point (PEP) such as &lt;a href=&quot;https://docs.pingidentity.com/pinggateway/2025.9/gateway-guide/stepup-sso-trx.html&quot;&gt;PingGateway&lt;/a&gt; or the &lt;a href=&quot;https://docs.pingidentity.com/web-agents/2025.9/index.html&quot;&gt;PingAgent&lt;/a&gt;, which interact with P1AIC or PingAM as the Policy Decision Point (PDP). Another pattern is to implement enforcement directly in applications via the &lt;a href=&quot;https://docs.pingidentity.com/sdks/latest/sdks/use-cases/how-to-perform-transactional-authorization.html&quot;&gt;Ping SDKs&lt;/a&gt; (JavaScript, iOS and Android).&lt;/p&gt;
&lt;p&gt;However, some customers who operate their own application gateways prefer to interact directly with the PDP REST APIs. This blog focuses on that third approach and provides a clear, end-to-end example using an automated shell script to demonstrate how the REST flow works.&lt;/p&gt;
&lt;p&gt;The high-level sequence of events for both application-based and gateway-based integrations is broadly the same. It’s explained in detail &lt;a href=&quot;https://docs.pingidentity.com/pingoneaic/latest/am-authorization/transactional-authorization.html#understand_transactional_authorization&quot;&gt;here&lt;/a&gt;, but here’s the simplified flow:&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;Use Case&lt;/h2&gt;
&lt;p&gt;In this blog, we demonstrate a REST-based approach to Transactional Authorization (TAuthZ) using an automated shell script. The scenario covers a high-risk operation — accessing an example &lt;code&gt;makePayment&lt;/code&gt; API&lt;br /&gt;
(&lt;code&gt;https://api.bankingexample.com:443/makepayment&lt;/code&gt;) via an &lt;code&gt;HTTP POST&lt;/code&gt; request.&lt;/p&gt;
&lt;p&gt;The script performs the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Authenticate the user using a standard login journey and obtain an SSO token&lt;/li&gt;
&lt;li&gt;Authenticate an admin using an admin-specific login journey in order to access the policy endpoint, issuing an SSO token with extended session durations (for example, a 60-minute idle and max time) so the client can cache it and improve performance.&lt;/li&gt;
&lt;li&gt;Calls the policy evaluation endpoint to request access to the protected &lt;code&gt;makePayment&lt;/code&gt; API.&lt;/li&gt;
&lt;li&gt;Receive a policy advice with a &lt;code&gt;TransactionConditionAdvice&lt;/code&gt; (TxId) from the PDP instructing the client to execute a Transactional Authorization journey (for example, OTP or push approval).&lt;/li&gt;
&lt;li&gt;Executes the required TAuthZ journey with this &lt;code&gt;TxId&lt;/code&gt;, collecting and completing the necessary callbacks for the one-time step-up authentication flow.&lt;/li&gt;
&lt;li&gt;Resubmits the policy evaluation request, now including the completed transactional context and &lt;code&gt;TxId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finally, receives a one-time authorization decision granting access to the sensitive API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This demonstrates how applications or gateways can interact directly with the PDP REST APIs to enforce secure, single-use authorization for high-risk operations.&lt;/p&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;Let’s get building 💪&lt;/p&gt;
&lt;p&gt;All assets are located &lt;a href=&quot;https://github.com/forgerock-dss/transactional_authorization/tree/main&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Import the Journeys&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For this example we’ll import three journeys:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NormalLogin&lt;/code&gt; — Used to simulate a standard user login.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AdminLogin&lt;/code&gt; — Used to simulate admin login with extended session timeouts.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TransactionalAuthZLogin&lt;/code&gt; — Used as the step-up authentication journey triggered by the TAuthZ policy.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;Download the journey export from &lt;a href=&quot;https://github.com/forgerock-dss/transactional_authorization/blob/main/journey_exports/normal_admin_and_transactional_journey_export.json&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;From the P1AIC Platform UI, navigate to Journeys on the left panel &amp;gt; Click Import &amp;gt; Take a Backup if required &amp;gt; Select Browse &amp;gt; Locate and open the file from step 1 &amp;gt; Click Next &amp;gt; Start Import&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once the import is complete, the three new journeys will appear as shown below. Note that the &lt;code&gt;TransactionalAuthZLogin&lt;/code&gt; journey should be a strong MFA journey. However, a simplified version has been used here for clarity in this blog.&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Import the Transactional Authorization Policy&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the policy XML file from &lt;a href=&quot;https://github.com/forgerock-dss/transactional_authorization/blob/main/policy_exports/Transactional_AuthZ_Policy_Export.xml&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;From the P1AIC Platform UI, expand Native Consoles &amp;gt; Click Access Management &amp;gt; Expand Authorization &amp;gt; Click Policy Sets.&lt;/li&gt;
&lt;li&gt;Click Import Policy Sets &amp;gt; Find the XML file from step 1 &amp;gt; Click Open&lt;/li&gt;
&lt;li&gt;Refresh the browser and the new &lt;code&gt;transactionalAuthZ&lt;/code&gt; Policy Set will appear.&lt;/li&gt;
&lt;li&gt;Clicking into it will show the &lt;code&gt;makePayment&lt;/code&gt; policy as shown below where:
&lt;ul&gt;
&lt;li&gt;The resource is defined as &lt;code&gt;https://api.bankingexample.com:443/makepayment&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The allowed action is &lt;code&gt;HTTP POST.&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The subject is set to &lt;code&gt;AuthenticatedUsers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The Transaction Environments condition targets the &lt;code&gt;TransactionalAuthZLogin&lt;/code&gt; journey.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create the Test Users and Apply Privileges&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;From the P1AIC Platform UI, Expand Identities &amp;gt; Click Manage &amp;gt; New Alpha realm — user &amp;gt; Create a user with the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Username: policy_user&lt;/li&gt;
&lt;li&gt;Firstname: Policy&lt;/li&gt;
&lt;li&gt;Lastname: User&lt;/li&gt;
&lt;li&gt;Email Address: &lt;a href=&quot;mailto:policy_user@example.com&quot;&gt;policy_user@example.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Password: &lt;code&gt;!!_SeCu4E@Pa55w04D$&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Repeat Step 1 but this time for the policy admin user:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Username: policy_admin&lt;/li&gt;
&lt;li&gt;Firstname: Policy&lt;/li&gt;
&lt;li&gt;Lastname: Admin&lt;/li&gt;
&lt;li&gt;Email Address: &lt;a href=&quot;mailto:policy_admin@example.com&quot;&gt;policy_admin@example.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Password: &lt;code&gt;!!_Adm1nSeCu4E@Pa55w04D$&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;From the Access Management Native Console, navigate to Identities &amp;gt; Groups tab &amp;gt; Add Group &amp;gt; Set the Group ID to &lt;code&gt;policy_admin&lt;/code&gt; &amp;gt; Create.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the &lt;code&gt;policy_admin&lt;/code&gt; user as a member and hit Save.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;From the Privileges tab, enable &lt;code&gt;Entitlement Rest Access&lt;/code&gt; and hit Save Changes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Execute the Script&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now that we have all the configuration in place, let’s bring it to life with the script.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the script from &lt;a href=&quot;https://github.com/forgerock-dss/transactional_authorization/blob/main/scripts/transactional_authZ.sh&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Modify the AM_URL to match your environment&lt;/li&gt;
&lt;li&gt;Execute the script to demonstrate the flow&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The output will look this like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;./transactional_authZ_DS.sh  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Getting cookie name  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CookieName is: XXXX&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;*********************  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Creating end-user SSO token for user: policy_user  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;End-user SSO token is: ZER7HY8OL...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;*********************  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Creating policy-admin SSO token for user: policy_admin  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Policy-admin SSO Token is: o0jzAU....&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;*********************  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Calling transactional policy: transactionalAuthZ  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Transaction Condition Advice Id is: 195b8505-3dba-4bbc-a71a-7debed2c2596&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;*********************  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Calling ../authenticate endpoint with Transaction Condition Advice Id: 195b8505-3dba-4bbc-a71a-7debed2c2596 to get callbacks&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;*********************  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Completing callbacks for submission  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Completed callback payload:  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;authId&quot;: &quot;eyJ0eXAiOiJKV1QiLC....74&quot;,  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;callbacks&quot;: [  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;....&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;*********************  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Calling authenticate endpoint with advice and completed callbacks  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;tokenId&quot;: &quot;ZER7HY8O....IwMQ..*&quot;,  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;successUrl&quot;: &quot;/enduser/?realm=/alpha&quot;,  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;realm&quot;: &quot;/alpha&quot;  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;*********************  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Finally, calling policy endpoint post transactional AuthZ with Transactional Conditional Advice Id of: 195b8505-3dba-4bbc-a71a-7debed2c2596  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;[  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;resource&quot;: &quot;https://api.bankingexample.com:443/makepayment&quot;,  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;actions&quot;: {  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;POST&quot;: true  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;},  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;attributes&quot;: {},  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;advices&quot;: {},  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&quot;ttl&quot;: 0  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;*********************&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Transactional Authorization (TAuthZ) is a powerful capability within PingOne Advanced Identity Cloud (P1AIC) and PingAM, enabling organisations to enforce strong, step-up authentication precisely at the moments where risk is highest. Whether approving a financial transaction, confirming a high-value action, or validating a user’s intent, TAuthZ offers a reliable way to introduce friction only when it truly matters.&lt;/p&gt;
&lt;p&gt;This blog illustrates how to execute a complete Transactional Authorization flow entirely over REST. By walking through user authentication, admin token retrieval, policy evaluation, TxId handling, step-up journey execution, and final policy re-evaluation, we showed how an application or custom gateway can interact directly with the PDP — while still leveraging the full power and flexibility of PingAM’s decisioning capabilities.&lt;/p&gt;</content:encoded></item><item><title>Smarter “Remember Me” with PingOne Protect</title><link>https://developer.pingidentity.com/blog/smarter-remember-me-with-pingone-protect/</link><guid isPermaLink="true">https://developer.pingidentity.com/blog/smarter-remember-me-with-pingone-protect/</guid><description>Smarter “Remember Me” with PingOne Protect: seamless, secure logins that adapt to risk without disrupting the user experience.</description><pubDate>Tue, 21 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;This post was originally published on &lt;a href=&quot;https://medium.com/@darinder.shokar/smarter-remember-me-with-pingone-protect-f71a54d7fd80&quot;&gt;Medium&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In the world of Identity and Access Management (IAM), it’s always a balancing act between security and user experience. Organisations want to introduce just the right amount of friction, at the right moment, and in the right context to protect users without disrupting them. The goal is to maintain a seamless, trusted customer journey while minimising drop-off and frustration.&lt;/p&gt;
&lt;p&gt;To achieve this, many businesses have implemented a “Remember Me” capability within their web channels. Once a user successfully signs in, subsequent visits allow them to be logged in automatically without re-entering their credentials — a familiar and convenient feature which is especially common in retail environments.&lt;/p&gt;
&lt;p&gt;However, “Remember Me” in isolation has its flaws. While it delivers convenience, it often lacks the intelligence to adapt when the context changes. For example, what if a user originally authenticates from the UK but suddenly appears to log in from Singapore — an &lt;em&gt;impossible traveller&lt;/em&gt; scenario? What if their IP address shifts unexpectedly, the login occurs at an unusual time, or even worse, a bot attempts access? Without continuously evaluating these contextual signals, “Remember Me” might meet the bar for user experience but falls short on adaptive security — failing to introduce the right friction at the right moment.&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;This is where &lt;a href=&quot;https://www.pingidentity.com/en/product/pingone-protect.html&quot;&gt;PingOne Protect&lt;/a&gt; steps in. It continuously analyses behavioural and contextual signals across multiple attack vectors to assign risk scores and trigger appropriate mitigation or action, to ensure convenience is not achieved at the expense of security.&lt;/p&gt;
&lt;p&gt;To learn more about the use cases for PingOne Protect integration with PingOne Advanced Identity Cloud (P1AIC) check out &lt;a href=&quot;https://docs.pingidentity.com/pingoneaic/latest/integrations/pingone-protect-use-cases.html&quot;&gt;this&lt;/a&gt; link.&lt;/p&gt;
&lt;h2&gt;Use Case&lt;/h2&gt;
&lt;p&gt;In this blog, we’ll enhance the &lt;a href=&quot;https://docs.pingidentity.com/auth-node-ref/latest/persistent-cookie-decision.html&quot;&gt;Persistent Cookie&lt;/a&gt; feature in PingOne Advanced Identity Cloud — the functionality that enables the “Remember Me” capability by integrating it with PingOne Protect.&lt;/p&gt;
&lt;p&gt;Here’s how it works:&lt;/p&gt;
&lt;p&gt;During the initial login, PingOne Protect evaluates the context and returns a risk score:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the score is low, a Persistent Cookie (PCookie) is set, and the login proceeds as normal.&lt;/li&gt;
&lt;li&gt;If the score is not low, no PCookie is set — effectively disabling “Remember Me” for that session, but does so silently, without disrupting the user experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On subsequent visits, if a valid PCookie is found, PingOne Protect performs another risk assessment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the risk remains low, the cookie is trusted, a new session is created automatically and the user is seamlessly signed in.&lt;/li&gt;
&lt;li&gt;If the risk is elevated, the user isn’t blocked outright; instead, the PCookie is deleted and they’re redirected to re-enter their credentials — introducing just the right level of friction, at the right moment, based on the current context and signals.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;Let’s get building! 💪&lt;/p&gt;
&lt;p&gt;Before we dive in, it’s worth noting that this solution showcases the power of the PingOne platform — apart from a single Custom Node used to display nodeState variables for clarity and education, it’s built entirely with out-of-the-box nodes, requiring no customisation or extensions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup a Mapped PingOne Environment&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In this section we’ll create a PingOne environment with PingOne Protect deployed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If you have a PingOne subscription navigate to &lt;a href=&quot;https://www.pingidentity.com/&quot;&gt;this&lt;/a&gt; page and hit “Sign On” at the top right of the page and login. On success you’ll be re-directed to the &lt;a href=&quot;https://console.pingone.eu/&quot;&gt;https://console.pingone.eu/&lt;/a&gt; page. If you don’t have a subscription, you can get a demo environment through this &lt;a href=&quot;https://www.pingidentity.com/en/try-ping.html&quot;&gt;link&lt;/a&gt;. Enter your business email address and hit “Try Ping”.&lt;/li&gt;
&lt;li&gt;From the PingOne Console &amp;gt; Hit Environments on the left panel &amp;gt; Blue + icon next to Environments.&lt;/li&gt;
&lt;li&gt;Select Build your own solution &amp;gt; click PingOne Protect &amp;gt; Hit Next.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On the environment name enter an appropriate name, for example &lt;code&gt;env-pingoneaic-**mycompany-ew2-sandbox1**&lt;/code&gt; &amp;gt; Select the region &amp;gt; Hit Finish.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Create a Worker Application&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Follow &lt;a href=&quot;https://docs.pingidentity.com/pingoneaic/latest/integrations/pingone-set-up-workers.html#create-a-worker-application-in-each-mapped-pingone-environment&quot;&gt;these&lt;/a&gt; steps to create OIDC credentials for the PingOne AIC tenant to integrate with PingOne Protect. Note the PingOne API and Authorization URLs, for example &lt;a href=&quot;https://auth.pingone.eu/&quot;&gt;https://auth.pingone.&lt;/a&gt;com, &lt;a href=&quot;https://auth.pingone.eu/&quot;&gt;https://auth.pingone.eu&lt;/a&gt; etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create Environment Secrets and Variables (ESVs) in P1AIC&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Follow &lt;a href=&quot;https://docs.pingidentity.com/pingoneaic/latest/integrations/pingone-set-up-workers.html#create-esvs-for-the-worker-application-credentials-in-each-tenant-environment&quot;&gt;these&lt;/a&gt; steps to create three ESVs that map to the PingOne Worker Credentials from the last step.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Additionally, create an ESV named &lt;code&gt;esv-hmac-signing-key&lt;/code&gt; (string secret) to sign the persistent cookie. Generate a 256-bit key using one of the following commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenSSL: &lt;code&gt;openssl rand -base64 32&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally create an ESV (string variable) called &lt;code&gt;esv-persist-cookie-domain&lt;/code&gt;with a value of the Fully Qualified Domain Name of your tenant. For example &lt;code&gt;openam-darinder-test.forgerock.io&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These ESVs make it easy to update configuration values when promoting to higher environments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Create a PingOne Service in P1AIC&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Follow &lt;a href=&quot;https://docs.pingidentity.com/pingoneaic/latest/integrations/pingone-set-up-workers.html#create-a-service-in-your-development-environment&quot;&gt;these&lt;/a&gt; steps to create a PingOne Service in your P1AIC tenant. For the secondary configuration be sure to use the ESVs defined above.&lt;/p&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;After creating the configuration set the PingOne API Server URL and Authorization Server URL as per the address noted in the “Create a Worker Application” section:
&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Import the Custom Display NodeState Node&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download &lt;code&gt;Display-NodeState.json&lt;/code&gt; from GitHub &lt;a href=&quot;https://github.com/forgerock-dss/remember_me_pingone_protect/tree/main/custom_nodes&quot;&gt;here&lt;/a&gt; to your local machine.&lt;/li&gt;
&lt;li&gt;From the P1AIC platform admin UI, expand Journeys on the left navigation panel &amp;gt; Custom Nodes&lt;/li&gt;
&lt;li&gt;Click Import Nodes (or Import if other Custom Nodes are present) &amp;gt; Browse &amp;gt; open &lt;code&gt;Display-NodeState.json&lt;/code&gt; &amp;gt; Import Nodes &amp;gt; Done. A new node called Output Variable from NodeState should be created.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Journey Import&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;From the &lt;code&gt;journey_exports&lt;/code&gt; directory &lt;a href=&quot;https://github.com/forgerock-dss/remember_me_pingone_protect/tree/main/journey_exports&quot;&gt;here&lt;/a&gt;, download the journey to your local machine.&lt;/li&gt;
&lt;li&gt;From the P1AIC platform admin UI, expand Journeys on the left navigation panel &amp;gt; click Journeys &amp;gt; Import.&lt;/li&gt;
&lt;li&gt;If need be take a backup or skip.&lt;/li&gt;
&lt;li&gt;Click Browse &amp;gt; find the &lt;code&gt;PersistWithProtect-journeyExport.json&lt;/code&gt; file &amp;gt; Open &amp;gt; Next &amp;gt; Start Import.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img /&gt;&lt;/p&gt;
&lt;p&gt;A few points to note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The PingOne Protect Evaluation nodes uses the default &lt;code&gt;Risk Policy Set ID.&lt;/code&gt; As a best practice a new risk policy should be created and the ID set in this parameter. From the PingOne Console &amp;gt; Expand Threat Protection &amp;gt; Risk Policies &amp;gt; Global Policies Blue + &amp;gt; Set a name &amp;gt; Configure as required &amp;gt; Apply &amp;gt; Copy the resulting Policy ID into this parameter. For example &lt;code&gt;a05cccb8-ada5–44e3-a6cd-cefdbc0c942f&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Additional &lt;code&gt;BOT_MITIGATION&lt;/code&gt; and &lt;code&gt;AITM_MITIGATION&lt;/code&gt; (Adversary-In-The-Middle) &lt;a href=&quot;https://docs.pingidentity.com/auth-node-ref/latest/pingone/pingone-protect-evaluation.html&quot;&gt;items&lt;/a&gt; were added to the Recommended Actions parameter of the PingOne Protect Evaluation nodes to demonstrate the node’s flexibility in mapping specific risk results to additional outcomes.&lt;/li&gt;
&lt;li&gt;The PingOne Protect Result node captures additional context just before the session is created, ensuring maximum accuracy for future assessment of the user’s risk posture and behaviour.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;Journey Breakdown&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This journey demonstrates how to implement a “Remember Me” (persistent login) flow enhanced with PingOne Protect risk evaluation.&lt;br /&gt;
It combines persistent cookie management with adaptive risk analysis to allow seamless logins for low-risk sessions while enforcing re-authentication for higher-risk ones.&lt;/p&gt;
&lt;p&gt;On every execution of the journey, the PingOne Protect Initialize node runs first to begin context and device data capture.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The journey then checks for the presence of a persistent cookie named &lt;code&gt;persist-session&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If persist-session is found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The PingOne Protect Evaluation node calls PingOne Protect to evaluate the context and calculate risk.&lt;/li&gt;
&lt;li&gt;For a Low risk outcome, the PingOne Protect Result node is invoked, and seamless “Remember Me” functionality is preserved.&lt;/li&gt;
&lt;li&gt;For any other outcome, the persistent cookie is removed, the PingOne Protect Risk value stored in nodeState is displayed for insight, and the user is redirected to authenticate again.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If persist-session is not found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user is prompted for their username and password, and the PingOne Protect Evaluation node again evaluates context and risk.&lt;/li&gt;
&lt;li&gt;If a Low risk outcome is returned, a new persistent cookie is set, enabling “Remember Me” on future logins.&lt;/li&gt;
&lt;li&gt;For all other outcomes (except ClientError, which shows an error message), the PingOne Protect Risk value is displayed for eudcation and understanding.&lt;/li&gt;
&lt;li&gt;Login is still permitted — the session proceeds, but without setting the persistent cookie — ensuring user access is not disrupted, only “Remember Me” functionality is withheld.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Demo&lt;/h2&gt;
&lt;p&gt;Check out the video below for a live demo&lt;/p&gt;

&lt;p&gt;PingOne Protect offers powerful monitoring and visual &lt;a href=&quot;https://docs.pingidentity.com/pingone/threat_protection_using_pingone_protect/p1_protect_dashboard.html&quot;&gt;dashboards&lt;/a&gt; that translate complex security data into clear, actionable insights. With real-time visibility into analysed events, risk trends, geolocation anomalies and high-risk user behaviour, organisations can quickly assess and respond to emerging threats. Here’s an example dashboard:
&lt;img /&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The integration of PingOne Protect with PingOne Advanced Identity Cloud elevates a simple “Remember Me” feature into an intelligent, adaptive security capability. By continuously evaluating contextual and behavioural risk, it ensures that convenience does not come at the expense of protection.&lt;/p&gt;
&lt;p&gt;Users enjoy seamless, low-friction logins when their behaviour is trusted, while higher-risk sessions automatically trigger the right level of friction — discreetly and without disruption. The result is a smarter, more secure “Remember Me” experience that balances usability with robust risk-based control — all achieved through a no-code, out-of-the-box Ping Identity platform implementation.&lt;/p&gt;</content:encoded></item></channel></rss>