Link to home
Start Free TrialLog in
Avatar of iftekhar sayyed
iftekhar sayyedFlag for United States of America

asked on

Acquire JWT Token from Azure AD using Angular 8 application

I have a very critical requirement for one of my projects. I have a Angular 8 application on the UI side and have Function apps on the Azure side. My requirement is as follows:
1) The moment user log ins there should be a call from angular to the microsoft site to acquire the jwt token, This token should be stored in the local storage.
2) Whenever there is a call to the API (Azure Function apps) from Angular this bearer token should be retrieved from the local storage and send in the header of the Api call.
3) before sending the token there should be a check is the token is not expired.
4) I have clientid,clientsecret information available.

I have the following code but its not fetching me the token from Azure:

 private url: string = 'https://login.microsoftonline.com/comcastcorp.onmicrosoft.com/oauth2/token';
  constructor(private http: HttpClient, private jwtHelper: JwtHelperService) { }

@Injectable({
  providedIn: 'root'
})
export class AuthService {

acquiretoken(): Observable<any> {
    let headers = new HttpHeaders({'Content-Type': 'application/x-www-form-urlencoded'});
    let body = new URLSearchParams();
    body.set('resource', "xxx-xxx-xxx");
    body.set('grant_type', "client_credentials");
    body.set('client_id', "xxx-xxx-xxx);
    body.set('client_secret', "xxx-xxx-xxx);

    return this.http.post<any>(this.url, body.toString(), {
      headers: headers
    }).pipe(
     [b] map(jwt => {[/b]
        if (jwt && jwt.access_token) {
          localStorage.setItem('apitoken', JSON.stringify(jwt))
        }
      })
    );
  }

Open in new window


Note: I get a error at below line of  code stating jwt undefined.
map(jwt => {


I am calling this function from other page

@Component({ templateUrl: 'home.component.html' })
export class HomeComponent {
    authcustomer: AuthCustomer;
    

    constructor(
          private msalService: MsalService,
        private apiauthService: AuthService
    ) {

    }



ngOnInit() {
       this.apiauthService.acquiretoken();
         }

Open in new window



This is very urgent and needs immediate help
I am not able to code this in Angualr 8 application.
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

If JWT is undefined then the URL you are calling is not returning it - not an Angular issue you need to find out why that URL is not returning data.

Have you checked the console and looked inside the request to see what is going on ?

Aside: have you considered using an Interceptor to automatically add the Authorization header to outgoing HTTP requests - will mean you don't have to construct the headers with each HTTP call [Note this won't solve your current problem - just noting it as a potential enhancement]

First up - check the response in the console, Second find out why that URL is not returning the data it should.
Avatar of iftekhar sayyed

ASKER

Hi Julian,

I am aware that the api call is not returning the JWT token and thats my issue
I am not able to figure out what is going wrong with that piece of code
thats why i need somebody to fix my issue.

Interceptor is fine, My only pain and the required solution is i need to get the JWT token with that api call
As I said - the code is not the problem.

Start with the URL

What does the console show - headers, parameters and response.

Check the documentation for the URL.

For instance when I try to make an AJAX call to that link I get a cross-origin request failure.

Are you sure this URL is usable from AJAX clients and not restricted to server to server calls which is usually the case with such URL's?

Please check the API docs and make sure that Cross Origin Requests are allowed.

Also check the console when this request is made - I am pretty sure you will get a CORS failure.
I agree what you are saying the URL is not returning anything, I need serious help not able to figure out how to fix this issue.
it does not show up any error saying incorrect url

This is the error i am getting

message: "jwt is not defined"
stack: "ReferenceError: jwt is not defined↵    at eval (eval at acquiretoken (http://localhost:4200/main.js:1784:13), <anonymous>:1:1)↵    at AuthService.acquiretoken (http://localhost:4200/main.js:1784:13)↵    at HomeComponent.ngOnInit (http://localhost:4200/main.js:1186:29)↵    at checkAndUpdateDirectiveInline (http://localhost:4200/vendor.js:64073:19)↵    at checkAndUpdateNodeInline (http://localhost:4200/vendor.js:74930:20)↵    at checkAndUpdateNode (http://localhost:4200/vendor.js:74869:16)↵    at debugCheckAndUpdateNode (http://localhost:4200/vendor.js:75891:62)↵    at debugCheckDirectivesFn (http://localhost:4200/vendor.js:75834:13)↵    at Object.eval [as updateDirectives] (ng:///AppModule/HomeComponent_Host.ngfactory.js:8:5)↵    at Object.debugUpdateDirectives [as updateDirectives] (http://localhost:4200/vendor.js:75822:21)"
__proto__: Error
My query is still unanswered, I need a code to  get this working and textual suggestions wont work out for me.
Pls send me a code which will get this resolved.
@iftechhar,

Let me say this again - the problem is not your code.

Did you understand what I said regarding CORS? This is fundamental to this problem. If the API you are using does not allow CORS then there is no code in existence that is going to solve your problem - you cannot make client (AJAX) requests to services that do not allow CORS - unless that service is on the same domain / protocol and port as the page making the request - which is clearly not the case here.

Please go and research CORS and what it is - it is important to understand this for you to solve your problem.

Your solution here is to setup your own service that you make your AJAX request to. This service then makes a call to the URL from the server (using cUrl or similar). This service receives the JWT and forwards it own to your client.

I need to emphasise this again. If access to this URL is being blocked by a CORS restriction - you cannot call that URL from your client code.
Hi Julian,
Can you help me out by giving info how to enable CORS in Azure to get this URL access to get the token
And I am not using Ajax I am using typescript to call the URL to get the token
Do you want me to send you the complete
Code for ref?
Is it possible for you to have a screen sharing session...messages are not working out any result
@iftekhar,

Best not to post bomb - just do one post.

Session sharing - not going to help in this case.
Send code - also not going to help

And I am not using Ajax I am using typescript to call the URL to get the token
This is where you need to do some research to improve the understanding of the systems you are dealing with.

Typescript has nothing to do with AJAX - it is simply the script you are using to code your Angular application.

Angular is making the call using the HTTPClient module - which IS AJAX. AJAX is simply the process of making a call using JavaScript (or compiled TypeScript) to a remote service.

Can you help me out by giving info how to enable CORS in Azure to get this URL access to get the token
No, this is prohibited for a reason. JavaScript code is not secure - you cannot allow API's that deal with sensitive information to run out of JavaScript. For this reason most API's disable CORS by default. You cannot enable it - only if you have control of the server on which the service resides can you do that (which in this case you can't).

As I have already stated the solution is

Your Client Code => AJAX REQUEST => Your Server script
Your Server Script => REMOTE REQUEST (cUrl or similar) => API
API => JWT to Your Server Script
Your Server Script => JWT To your Client Code

Open in new window


That is how we integrate to external API's that do not implement CORS.

I state again - you cannot solve this in your Angular code.
In my current code I am already getting token for Authenticating user that works but when I am trying to get token from Azure AD B2C then I am having issues. The code is similar. That is working fine without issues
@iftekhar,

I don't know how else to say this - if the URL you are using is returning a CORS error it is not going to work from your Angular code.

Do you have a link to their API documentation that describes how to use their API? I feel we might make more progress going that route. As I have explained you can't get around CORS for security reasons so either you are trying to use the API in a way it is not meant to be used or there is an aspect to this that has not been made clear. Therefore, let's go to the API docs and take it from there.
Hi Julian,

My apology it was mid night time and i was constantly looking for your answers so was replying  from my cell phone.
This is the list of endpoints i see in my Azure AD b2c (Pls see the attached)
Under documentation Tab i see following links

Documentation
Azure Active Directory B2C overview
Application types
Code samples and tutorials

What documentation you want?
The documentation for the URL you are trying to use. I am not familiar with the environment, however API's generally follow the same patterns so once we have the API documentation - which should describe how to use the API - the rest should follow - but I cannot tell you where to find that documentation.

Where did you get the URL from?
I got the URL from the Endpoints , If you look at the attached snapshot you will find the URL there
For e.g look at  the below:

https://login.microsoftonline.com/46a31020-4d06-4709-9671-6f1e9f58829d/oauth2/token
That is not an API - you can't just lift a URL from an existing application and use it.

What I am seeing is that this is not a recognized API that you are using - you are trying to make it work in your app - which is not going to happen.
Hi Julian,

I was talking to few of the team members out here and there was some confusion though.
This is what we are looking for.
Angular 8 application will acquire the access token/jwt token from Azure Active Directory

So to cut down and make it simple, I need to get a JWT token from Azure AD, Can you pls suggest the best way to do it ad if you can share some code which i can integrate in my application and do this successfully.(Forget about my code as of now)

Thanks,
Iftekhar
No, I have no experience with AD - I picked this up as an Angular question.

If Azure provides a means to do this then it will published in an API / documentation somewhere.

I found this link - https://aadguide.azurewebsites.net/integration/jwts/ which suggests what I was referring to earlier - a Server side script that fetches the token.

If that works then (as I described above) you proxy the request to Azure through an intermediary script you create that does a server to server (i.e. not AJAX) call.

Your Angular code then calls your script and gets the JWT that way.
Thanks Julian, Can you direct this question somebody from your team who is aware of this scenario and knows about Azure AD

THANKS
@iftekhar,

There is no team - we are all volunteers who respond to questions. I am not aware of anyone with those specific skills you can talk to. You can "Request Attention" on this thread and ask a Mod to send out to other experts.

Having said that I feel that you have not really grasped what I have been saying in my posts regarding an intermediary service. I am pretty sure this is the way to go. I am also pretty sure if you cannot find an API document to describe how to do this, or find a working example of where it is in use then in all likelihood it is unsupported.

The CORS issue means you cannot do this from the client. You can try, as I mentioned before, building a service (.Net or similar) that does a server to server call for the JWT and returns that to the client - in my view this the best option.
Hi Julian,

I understand whatever you have mentioned, I mentioned this earlier and again retreating if my approach is not workable
can you provide me some code for Angular which can do this. I know you are a Angular expert.

I am pretty sure there would be ways to do this in Angular as this is not the one of a kind scenario this is a very common scenario.

Thanks and waiting to hear back from you with a appropriate solution
I guess i got some solution, so lets stop this thread here.

Thanks
I am pretty sure there would be ways to do this in Angular as this is not the one of a kind scenario this is a very common scenario.
If it is a very common scenario there would be an API describing it.

Given the URL you have provided - I don't see how it can be common to JavaScript applications given the URL returns a CORS error when used from within an AJAX call.

Find the API that documents the scenario you are interested in (or another use case where it is being successfuly used) and let's go from there.

From where I am sitting though there is no direct Angular solution - you need to work through a proxy.

Where did you find the URL you are using at the moment

https://login.microsoftonline.com/comcastcorp.onmicrosoft.com/oauth2/token

Where did that come from?
I guess i got some solution, so lets stop this thread here.
Could you post it here so others who might have this issue can benefit from it.
Hi Julian,

I was on vacation so did not check your messages, Unfortunately the solution which i mentioned did not work as expected.
I am keeping this thread alive until we get to a solution. I will share some details shortly which will enable you to give advice me appropriate solution to achieve this functionality.

Will it be possible for you to discuss on a call or through screen share whatever best suits you.
Will it be possible for you to discuss on a call or through screen share whatever best suits you.
Unfortunately not. I am only available to answer posts at this stage.

Have you managed to find any documentation that describes the API you are using - specifically in how to use it with an AJAX call?
Hi  Julian,

I was able to gather some more information on the token issue and these are my findings.

1) This is the correct endpoint which is used to acquire the token from Azure AD
URL: https://login.microsoftonline.com/<Tenant ID>/oauth2/token

This url i got from the Azure app registration page under Endpoints link (Pls see attached).
I am also attaching the txt file it has the code for the app module.

Now the issue which i am facing is after running the application i get below CORS error in my console log and my application is never able to reach the endpoint to get the token.

1)      zone-evergreen.js:2952 GET https://login.microsoftonline.com/906aefe9-76a7-4f65-b82d-5ec20775d5aa/oauth2/token/v2.0/.well-known/openid-configuration 404 (Not Found)

2)      :4200/#/:1 Access to XMLHttpRequest at 'https://login.microsoftonline.com/906aefe9-76a7-4f65-b82d-5ec20775d5aa/oauth2/token/v2.0/.well-known/openid-configuration' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

I am not sure from where it is adding the  following portion to the url
v2.0/.well-known/openid-configuration

Because of this the URL is failing.

Can you pls suggest me a solution to fix this issue and get things working

Note: path to the documentation
https://docs.microsoft.com/en-us/azure/active-directory/develop/developer-support-help-options
Token-Endpoint.PNG
token-code.txt
The CORS error means you cannot call it from your JavaScript (client) code (as I have explained before).

That endpoint is for a server to server call - not client to server. The way to use (again as I have outlined) is to proxy it through your own server script that makes the OAuth call to the endpoint and then returns the token to your client.
You have mentioned  this answer in our earlier posts.Sonot of much help to me.
My original question remains unanswered why and from where does the last portion gets added to the endpoint.
Sonot of much help to me
You want a square circle. I am telling you you can't have a square circle and you are saying that does not help you.

Good luck with that.

CORS means you can't call from the client. But keep trying.

I am signing off now as I cannot spend time on explaining this any more.

You can't call that API directly from a JavaScript (browser based) client.
It seems you dont have any patience at all, I am asking you for a solution or code sample which will give me a right direction. But every time you are giving me the same answer with different ways. After wasting so much days and time my query is still not resolved.
You are not able to give any solution to my query apart from just pasting the comments which are already present on different  blogs or sites.
This is not expected , i am very disappointed with this site and its experts

the website name is Experts Exchange, But i dont see a single expert on this site. Seems to be just a fake site and nothing else
i wont sign off so easily untill and unless i get a workable solution, This is not a free service i am paying for it to get help.
I have sent you a PM on this.

If you feel you are not getting the response you need - please feel free to request attention on this question and ask a moderator for assistance.
This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.