Using Active Directory Federation Services (ADFS) to Authenticate / Authorize Node.js Apps in Windows Azure
It’s gotten easy to publish web applications to the cloud, but the last thing you want to do is establish unique authentication schemes for each one. At some point, your users will be stuck with a mountain of passwords, or, end up reusing passwords everywhere. Not good. Instead, what about extending your existing corporate identity directory to the cloud for all applications to use? Fortunately, Microsoft Active Directory can be extended to support authentication/authorization for web applications deployed in ANY cloud platform. In this post, I’ll show you how to configure Active Directory Federation Services (ADFS) to authenticate the users of a Node.js application hosted in Windows Azure Web Sites and deployed via Dropbox.
[Note: I was going to also show how to do this with an ASP.NET application since the new “Identity and Access” tools in Visual Studio 2021 make it really easy to use ADFS to authenticate users. However because of the passive authentication scheme Windows Identity Foundation uses in this scenario, the ASP.NET application has to be secured by SSL/TLS. Windows Azure Web Sites doesn’t support HTTPS (yet), and getting HTTPS working in Windows Azure Cloud Services isn’t trivial. So, we’ll save that walk-through for another day.
Configuring Active Directory Federation Services for our application
First off, I created a server that had DNS services and Active Directory installed. This server sits in the Tier 3 cloud and I used our orchestration engine to quickly build up a box with all the required services. Check out this KB article I wrote for Tier 3 on setting up an Active Directory and ADFS server from scratch.
ADFS is a service that supports identity federation and supports industry standards like SAML for authenticating users. It returns claims about the authenticated user. In ADFS, you’ve got endpoints that define which inbound authentication schemes are supported (like WS-Trust or SAML), certificates for signing tokens and securing transmissions, and relying parties which represent the endpoints that ADFS has a trust relationship with.
In our case, I needed to enabled an active endpoint for my Node.js application to authenticate against, and one new relying party. First, I created a new relying party that referenced the yet-to-be-created URL of my Azure-hosted web site. In the animation below, see the simple steps I followed to create it. Note that because I’m doing active (vs. passive) authentication, there’s no endpoint to redirect to, and very few overall required settings.
- Visualize your Azure resources and usage patterns
- Associate business activities with cloud usage
- Leverage Azure crowd sourced knowledge and best practices
Sign Up for Newvem Analytics for Azure
At this point, ADFS was fully configured and able to authenticate my remote application. The final thing to do was enable the appropriate authentication endpoint. By default, the password-based WS-Trust endpoint is disabled, so I flipped it on so that I could pass username+password credentials to ADFS and authenticate a user.
Connecting a Node.js application to AD FS
Next, I used the JetBrains WebStorm IDE to build a Node.js application based on the Express framework. This simple application takes in a set of user credentials, and attempts to authenticate those credentials against ADFS. If successful, the application displays all the Active Directory Groups that the user belongs to. This information could be used to provide a unique application experience based on the role of the user. The initial page of the web application takes in the user’s credentials.
div.content h1= title form(action='/profile', method='POST') table tr td label(for='user') User td input(id='user', type='text', name='user') tr td label(for='password') Password td input(id='password', type='password', name='password') tr td(colspan=2) input(type='submit', value='Log In')
This page posts to a Node.js route (controller) that is responsible passing those credentials to ADFS. How do we talk to ADFS through the WS-Trust format? Fortunately, Leandro Boffi wrote up a simple Node.js module that does just that. I grabbed the wstrust-client module and added it to my Node.js project. The WS-Trust authentication response comes back as XML, so I also added a Node.js module to convert XML to JSON for easier parsing. My route code looked like this:
//for XML parsing var xml2js = require('xml2js'); var https = require('https'); //to process WS-Trust requests var trustClient = require('wstrust-client');</p> <p>exports.details = function(req, res){</p> <p>var userName = req.body.user; var userPassword = req.body.password;</p> <p>//call endpoint, and pass in values trustClient.requestSecurityToken({ scope: 'http://seroternodeadfs.azurewebsites.net', username: userName, password: userPassword, endpoint: 'https://[AD FS server IP address]/adfs/services/trust/13/UsernameMixed' }, function (rstr) {</p> <p>// Access the token var rawToken = rstr.token; console.log('raw: ' + rawToken);</p> <p>//convert to json var parser = new xml2js.Parser; parser.parseString(rawToken, function(err, result){ //grab "user" object var user = result.Assertion.AttributeStatement[0].Attribute[0].AttributeValue[0]; //get all "roles" var roles = result.Assertion.AttributeStatement[0].Attribute[1].AttributeValue; console.log(user); console.log(roles);</p> <p>//render the page and pass in the user and roles values res.render('profile', {title: 'User Profile', username: user, userroles: roles}); }); }, function (error) {</p> <p>// Error Callback console.log(error) }); };
See that I’m providing a “scope” (which maps to the relying party identifier), an endpoint (which is the public location of my ADFS server), and the user-provided credentials to the WS-Trust module. I then parse the results to grab the friendly name and roles of the authenticated user. Finally, the “profile” page takes the values that it’s given and renders the information.
div.content h1 #{title} for #{username} br div div.roleheading User Roles ul each userrole in userroles li= userrole
My application was complete and ready for deployment to Windows Azure - Check out how to publish a Node.js application to Windows Azure Cloud.
Testing the application
The whole point of this application is to authenticate a user and return their Active Directory role collection. I created a “Richard Seroter” user in my Active Directory and put that user in a few different Active Directory Groups.
I then browsed to my Windows Azure Website URL and was presented with my Node.js application interface.
I plugged in my credentials and was immediately presented with the list of corresponding Active Directory user group membership information.
Summary
That was fun. ADFS is a fantastic way to extend your on-premises directory to applications hosted outside of your corporate network. In this case, we saw how to create Node.js application that authenticated users against ADFS. While I deployed this sample application to Windows Azure Web Sites, I could have deployed this to ANY cloud that supports Node.js. Imagine having applications written in virtually any language, and hosted in any cloud, all using a single authentication endpoint. Powerful stuff!
About the Author
Richard Seroter is a Product Manager for cloud computing provider Tier 3, a Microsoft MVP, blogger, author, trainer and frequent public speaker. He has spent the majority of his career working with organizations as they planned and implemented their enterprise software solutions. Richard worked first for two global IT consulting firms where he gained exposed to a diverse range of industries, technologies, and business challenges. Then, Richard joined Microsoft as a SOA/BPM technology specialist where his sole objective was to educate and collaborate with customers as they considered, designed, and built application integration solutions. He then accepted a job at biotechnology leader Amgen where he designed a wide range of global systems before becoming the lead architect of the R&D division. Richard now works at Tier 3 as a Product Manager where he contributes to product strategy and development while actively collaborating with the cloud computing community. Richard is the author or contributor to three recent books: “Applied Architecture Patterns on the Microsoft Platform” (Packt Publishing, 2020) , “SOA Patterns with BizTalk Server 2009? (Packt Publishing, 2009) , and “Microsoft BizTalk 2020: Line of Business Systems Integration” (Packt Publishing, 2011).
Contact him
Originally posted here - http://seroter.wordpress.com/2022/04/22/using-active-directory-federation-services-to-authenticate-authorize-node-js-apps-in-windows-azure/
Keywords: Microsoft Azure, Windows Azure, Azure Cloud, Azure Public Cloud, Virtual Machines, Node.js, Dropbox, SDK, Active Directory Federation Services, ASDF, Security, SAML, IAM, Security, Users Management, Cloud, Node.js, Enterprise Cloud Platform, Windows Azure, Identity and Access Management, Javascript, Webserver
You must be logged in to post a comment.