MSAL and passporrt-azure-ad cannot verify token - javascript

I have not been able to link the Azure Active Directory access control in our ReactJS application to our API, and reading through the documentation on this matter has left me with more questions than answers.
I first began by following the instructions in the AAD Single-page app scenario, which was straightforward and allowed me to log in to my AAD account on the web, which I mentioned previously. That worked well.
However, when it came to configuring our NodeJS API, I was presented with two options: A Web app that calls web APIs, and Protected web API.
In A Web app that calls web APIs, the registration was straightforward and led me to believe that this was the way to go, however the Code Configuration page states that only ASP, Java, and Python are supported. I was unable to find any JavaScript examples for this scenario, so I moved on to Protected Web API.
Similarly, while I found the registration portion to be easy to follow, the Code Configuration page only listed examples in .NET, NodeJS (but only for App Functions, rather than a standalone API), and Python. Given that the NodeJS example was close enough to a standalone API, I followed along with that code, substituting our configuration options where appropriate, seeing as it used the passport-azure-ad package that I saw elsewhere and previously had tried to implement. However, in both cases, every attempt to make an API call against the protected endpoint resulted in the API logging the following:
“authentication failed due to: In Strategy.prototype.jwtVerify: cannot verify token”
Additionally, and I’m not sure how related this could be, but I noticed that when I decoded the ID Token and Access Token on the ReactJS application, the ID Token version was 2.0, but the Access Token was 1.0. Searching through Github Issues and StackOverflow showed that others had observed this behavior as well, although I was unable to replicate their processes in order to get a v2.0 Access Token, which I suspect but am not sure is the reason for the inability for the NodeJS API to verify the token.
Oh, and I have observed the same behavior when using MSAL.js 1.3 as well as the 2.0 beta in the client, in case that helps.

The comments discussion helped me discover a solution that was otherwise not made obviously clear in the MSAL examples and documentation, which was that any MS Graph scopes in the Login Request (ex: "User.Read") would downgrade Access Tokens from v2.0 to v1.0, which is why I was receiving v2.0 ID Tokens with v1.0 Access Tokens.
I removed all Graph scopes from the Login Request, with the API scope being the only one remaining, and as a result the following login returned a v2.0 Access Token, which was subsequently validated by the API and enabled authenticated access.

Related

Setting up a development environment for working with 0Auth 2.0

I'm curious if anyone else has encountered this issue.
I am building an application that will authenticate users using Google 0Auth 2.0 + OpenID.
I've built a simple site just with HTML and CSS to hold the UI and I'm using live server in Vscode to view it.
In The Google developer console for oauth, you must set Authorised JavaScript origins for client-side applications. I assumed I would just set this to http://localhost:5500 for the port that live server uses but I always get the following error:
Authorization Error
Error 400: invalid_request
Permission denied to generate login hint for target domain.
I have got around the issue by just getting a domain and hosting for a test site and setting this as the "Authorised JavaScript origin". However is seems really clunky and I have to FTP all my files to my hosting provider every time I want to change my code.
I could also host everything on a Node.js server from my local machine but this would just cause the same issue as before.
My question isn't so much how to stop getting this error but what is the proper way of developing with OAuth 2.0 and is there any way to speed up the process/create a local environment that doesn't get the same errors.
Thanks for your help.
There is an answer to this Google question here that may help you.
The way I have always set up an OAuth environment is to try to avoid localhost and use more real world URLs on a Developer PC. I also like to split them like this which helps me to visualize the architecture:
Base URL
Represents
http://www.example.com -
Your web UIs
http://api.ecample.com
Your APIs
http://login.example.com
The Authorization Server
This approach can also give you more confidence that your code will work well in beowsers, in areas such as these:
CORS
Cookies
Content Security Policy
By default you just need to edit your hosts file and add an entry like this. It can work very well for demos to business people also.
127.0.0.1 localhost www.example.com api.example.com login.example.com
:1 localhost
ADVANCED SCENARIOS
At Curity we provide some quite advanced developer setups and this approach scales well, as in the below articles. The second of these also provides a script you can use to run locally over SSL, in case this is ever useful:
Single Page Apps End to End Developer Setup
Kubermetes End to End Developer Setup

Using Active Directory (with LDAP) to authenticate on an angularjs/javascript fronted - what should the flow of the process be?

I'm working on a project in which we need to authenticate the user in an application by using his/hers windows credentials. Frontend is using Angularjs and backend java.
After doing a sensible amount of research, I discovered that there is no way on the the frontend to obtain directly the Windows user & pass due to security concerns.
But I'm thinking that the whole process should start here, from the frontend, by obtaining these two encrypted credentials or at least a token and sending them to the backend in order to kickstart the ntlm authentication process.
And also, not sure if the user should have to log in the app by typing his windows credentials or if it should automatically be done with ntlm passthrough.
I do not have a good grip on the concept, and that is because most of the related sources that I found are referring to backend solutions (C# 80% of them), but almost nothing for fronted. So, I humbly require some clarifications on this topic. Is there some sort of middleware or npm package that I should use in order to obtain the user & pass, or what would you advise?
Web servers expose certain server variables to code handling requests they serve.
For me, using IIS, these are described here: https://learn.microsoft.com/en-us/previous-versions/iis/6.0-sdk/ms524602%28v%3dvs.90%29
Since I am using IISNode; my node.js environment is completely embedded into IIS; I have access to these server variables. As the link described, each programming language seems to have their own way to access these variables.
So I would doubt it if Java does not have those as well. The exact code to use will depend on you back end.
But a quick search for "java server variables" already yields me the following:
https://docs.oracle.com/cd/E19534-01/820-3288/gawim/index.html for the java access manager.
http://users.polytech.unice.fr/~buffa/cours/internet/POLYS/servlets/Servlet-Tutorial-CGI-Variables.html for old school JSP.
How can I obtain server variables using apache wicket 1.54? for java wicket server.
So have a look at the documentation of your specific web server software or Java API.
There should be a list and example code of how to access these.
Once you obtain this data server side, you can do the LDAP query and then return the results client side.

Upload from Client Browser to Google Cloud Storage Using JavaScript

I am using Google Cloud Storage. To upload to cloud storage I have looked at different methods. The method I find most common is that the file is sent to the server, and from there it is sent to Google Cloud storage.
I want to move the file directly from the user's web browser to Google Cloud Storage. I can't find any tutorials related to this. I have read through the Google API Client SDK for JavaScript.
Going through the Google API reference, it states that files can be transferred using a HTTP request. But I am confused about how to do it using the API client library for JavaScript.
People here would require to share some code. But I haven't written any code, I have failed in finding a method to do the job.
EDIT 1: Untested Sample Code
So I got really interested in this, and had a few minutes to throw some code together. I decided to build a tiny Express server to get the access token, but still do the upload from the client. I used fetch to do the upload instead of the client library.
I don't have a Google cloud account, and thus have not tested this, so I can't confirm that it works, but I can't see why it shouldn't. Code is on my GitHub here.
Please read through it and make the necessary changes before attempting to run it. Most notably, you need to specify the location of the private key file, as well as ensure that it's there, and you need to set the bucket name in index.html.
End of edit 1
Disclaimer: I've only ever used the Node.js Google client library for sending emails, but I think I have a basic grasp of Google's APIs.
In order to use any Google service, we need access tokens to verify our identity; however, since we are looking to allow any user to upload to our own Cloud Storage bucket, we do not need to go through the standard OAuth process.
Google provides what they call a service account, which is an account that we use to identify instances of our own apps accessing our own resources. Whereas in a standard OAuth process we'd need to identify our app to the service, have the user consent to using our app (and thus grant us permission), get an access token for that specific user, and then make requests to the service; with a service account, we can skip the user consent process, since we are, in a sense, our own user. Using a service account enables us to simply use our credentials generated from the Google API console to generate a JWT (JSON web token), which we then use to get an access token, which we use to make requests to the cloud storage service. See here for Google's guide on this process.
In the past, I've used packages like this one to generate JWT's, but I couldn't find any client libraries for encoding JWT's; mostly because they are generated almost exclusively on servers. However, I found this tutorial, which, at a cursory glance, seems sufficient enough to write our own encoding algorithm.
I'd like to point out here that opening an app to allow the public free access to your Google resources may prove detrimental to you or your organization in the future, as I'm sure you've considered. This is a major security risk, which is why all the tutorials you've seen so far have implemented two consecutive uploads.
If it were me, I would at least do the first part of the authentication process on my server: when the user is ready to upload, I would send a request to my server to generate the access token for Google services using my service account's credentials, and then I would send each user a new access token that my server generated. This way, I have an added layer of security between the outside world and my Google account, as the burden of the authentication lies with my server, and only the uploading gets done by the client.
Anyways, once we have the access token, we can utilize the CORS feature that Google provides to upload files to our bucket. This feature allows us to use standard XHR 2 requests to use Google's services, and is essentially designed to be used in place of the JavaScript client library. I would prefer to use the CORS feature over the client library only because I think it's a little more straightforward, and slightly more flexible in its implementation. (I haven't tested this, but I think fetch would work here just as well as XHR 2.).
From here, we'd need to get the file from the user, as well as any information we want from them regarding the file (read: file name), and then make a POST request to https://www.googleapis.com/upload/storage/v1/b/<BUCKET_NAME_HERE>/o (replacing with the name of your bucket, of course) with the access token added to the URL as per the Making authenticated requests section of the CORS feature page and whatever other parameters in the body/query string that you wish to include, as per the Cloud Storage API documentation on inserting an object. An API listing for the Cloud Storage service can be found here for reference.
As I've never done this before, and I don't have the ability to test this out, I don't have any sample code to include with my answer, but I hope that my post is clear enough that putting together the code should be relatively straightforward from here.
Just to set the record straight, I've always found OAuth to be pretty confusing, and have generally shied away from playing with it due to my fear of its unknowns. However, I think I've finally mastered it, especially after this post, so I can't wait to get a free hour to play around with it.
Please let me know if anything I said is not clear or coherent.

Why does Ember-Simple-Auth support refresh tokens? (JS + OAuth 2.0)

From what I've read in the OAuth 2.0 specs so far, it is not recommended to store any confidential information in the browser where it would be accessible via Javascript.
The discussion here also seems to agree on this point:
Using OAuth2 in HTML5 Web App
I am currently building an Ember-based app as a frontend to my REST-style API backend, and I am using Ember-Simple-Auth as a library for handling the user login, which implements the Resource Owner Password Credentials workflow and also explicitly supports refresh tokens.
I read that the "Resource Owner Password Credentials" grant type in OAuth 2.0 allows the usage of refresh tokes, but the text in this paragraph is written addressing a very general definition of client.
As Ember.js is a framework for writing single page webapps running in the browser, I am now wondering...
Would it be safe to use the refresh token in an Ember app? The discussion mentioned above seems to disagree. Which leads me to:
Why does Ember-Simple-Auth support refresh tokens?
Thanks for taking the time to consider.
Best! Marcus
The only point where using a refresh token is less safe than not using one is when the refresh token doesn't expire. So if someone gets physical access to your machine (or sth. is broken wrt HTTPS), the access token might already have been expired while the refresh token is still active and can be used to obtain fresh access tokens (meaning the security hole stays forever).
Support for that was built into Ember.SimpleAuth by popular demand. There are 2 things to say about it though: besides from the user heaving to make sure no one gets physical access to their machines (which is a required security strategy for most sites as no sites usually expire sessions or only after very long time) it's vital that client and server only communicate via (correctly set up) HTTPS. The second thing is that Ember.SimpleAuth only uses a refresh token when there's one in the server response. So if your'e concerned about that (which in my opinion is right) don't enable refresh tokens on the server side in the first place.

How to do OAuth authentication via AJAX / jQuery?

I've worked a bit with Twitter web API, I know it works with OAuth, I've consumed the API using a python library. I've also tried a bit of Instagram API using a Java Script small library.
I know those perform web REST requests in the background, authenticating first and then querying requests as I code.
However, what if I want to perform the requets using jQuery $.ajax from a web application?
I've read some docs and sites and it seems it's just possible. Like only ajaxing to the API routes, starting with the authentication route.
But, how does this process work? I mean, I query by AJAX to the auth route and then how do I keep track of that authentication. How to keep that communication? Will the redirect URL play its role then?
Reading this site for Instagram API I start getting a clue about it, but got the doubts mentioned above.
I want to perform all AJAX requests in the Java Script server background (I'm using node.js), assuming I will provide my apps OAuth in the $.ajax. Is that OK or I can actually code it on client site keeping my OAuth tokens save?
And, if it's concern of this same question, when it comes to bytes (pictures, sound, etc) how to catch the response from API.
Okay, if I understand what you are trying to do is to make an Ajax call from a web page to the Twitter API and post/retrieve tweets and other info from Twitter.
Since the release of the API v1.1, Twitter has deprecated the v1.0 API and one of the major changes in 1.1 was Authentication Required on all Endpoints
And to do this from JavaScript and jQuery is quite possible (albeit very cumbersome, difficult and requires the use of many 3rd party JS libraries to HMAC Hash your data and keys and calculate content lengths on the client side before making your Request. Twitter API does not support CORS but does support JSONP for these kind of Ajax requests. But this is not recommended - since doing this on the client side will require you to have your Twitter App Access Keys - Private keys - embedded in your script files - which is basically a big NO-NO. And hence a server side solutions to generate your oAuth tokens is recommended. But once you have achieved that, it may be easier to get the token on your script and make Ajax calls using that from the browser. But I haven't gone that far in my research.
Also, this is based off of my research in Mid 2013 when my Twitter Ajax widgets stopped working because of this change and I gave up trying to fix it using that route after I realized it would compromise my security keys. Things may have changed since then.
If you are still interested to find a solution, this walkthrough would be a good place to start learning about Twitter's oAuth and how the Access Tokens are generated: https://dev.twitter.com/docs/auth/oauth

Categories

Resources