using headers in HTTP client - angular7

I am trying to develop a dashboard in angular 7. I wanted to access an URL and get the JSON response in my dashboard. the problem is that my code works fine with an open source URL. but there are few end points, which have authorization request. Aim is to add the headers like the JWT token, authorization to my service and display the data in my dashboard.
I found few resources on the internet which are confusing.
Below is my code I tried in my service.ts
import { Injectable } from '#angular/core';
import {HttpClient} from "#angular/common/http";
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getlocations() {
return this.http.get('https://jsonplaceholder.typicode.com/users')
}
}
Any lead on how to add the header and access them would be really helpful.

The simplest way is to modify a specific request by adding HttpHeaders with the authorization parameter. Here's an example:
getlocations() {
return this.http.get(
'https://jsonplaceholder.typicode.com/users',
{ headers: new HttpHeaders({'Authorization': 'Bearer ' + token}) }
);
}

Related

NestJS req.body from POST method is empty/undefined when awaiting ArrayBuffer

I am trying to send file from Client (Angular) to the NestJS same way like it is working now with Java-springboot API.
I am using POST method in NestJS but, unfortunatelly I am not able to got any data from the body :
here is the code :
#Post('/uploadExportFile')
uploadAttachment(#Req() req: Request, #Body() attachment: ArrayBuffer): any {
console.log(attachment);
return {};
}
content-type is set in header on Client side, I am not sure if I need to set content-types there ? Content type depends on file mimetype it should be (application/pdf/png/jpeg)..not multiform or what I need to do to achieve that attachment object will not return empty {} .
req.body is undefined
What I need to do with that file is to again change it back to Base64 (in angular it is in Base64) but Java API consumes only byte[] so I need to keep that like it is on FE.
any suggestions what is wrong in this "simple" code?
** EDIT **
====↓ EDIT ↓====
Solution: request.body is undefined is:
NestJS use as default body jsonBody, so in that case you have to override for specific routes that you want to use raw-body, and if raw-body is used insted of jsonBody, then the body from request is not undefined and it contain ArrayBuffer.
What you need to do is something like this;
Create rawBody middleware raw-body.middleware.ts
import { Injectable, NestMiddleware } from '#nestjs/common';
import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';
#Injectable()
export class RawBodyMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => any) {
bodyParser.raw({type: '*/*'})(req, res, next);
}
}
app.module.ts
export class AppModule implements NestModule {
public configure(consumer: MiddlewareConsumer): void {
consumer
.apply(RawBodyMiddleware)
.forRoutes({
path: '/uploadExportFile',
method: RequestMethod.POST,
})
.apply(JsonBodyMiddleware)
.forRoutes('*');
}
}
and you need to disable bodyparser in main.ts
const app = await NestFactory.create(AppModule, { bodyParser: false })
in new version of NestJS is introduced new option raw-body but I have no possibility to test that https://docs.nestjs.com/faq/raw-body#raw-body
frist thing send the content-type application/x-www-form-urlencoded
and sure you have add UseInterceptors Like FileInterceptor
you can import FileInterceptor
if you need to get buffer try use file.buffer
import {FileInterceptor} from "#nestjs/platform-express";
#Post('upload')
#UseInterceptors(FileInterceptor('file'))
async upload(#Req() request: RequestWithUser, #UploadedFile() file) {
if (!file) {
throw new HttpException('File is required', HttpStatus.BAD_REQUEST);
}
// you have file
return await this.storageService.upload(file, request.user);
}

Get JWT token in NextJS API

I created a NextJS application integrated with Amazon Cognito. I have a landing page that is using the Amplify Auth API (not the components). Now I need to call an external API to do CRUD operations. What's the best way to do this in NextJS?
I'm thinking I'll create an API in NextJS that will forward the request to the actual external REST API. But my problem is I'm not able to get the JWT Token on the API, since it's a backend code.
A code like this:
Auth.currentSession().then(data => console.log(data.accessToken.jwtToken));
Obviously won't work:
[DEBUG] 20:42.706 AuthClass - Getting current session
[DEBUG] 20:42.706 AuthClass - Failed to get user from user pool
[DEBUG] 20:42.707 AuthClass - Failed to get the current user No current user
(node:20724) UnhandledPromiseRejectionWarning: No current user
How can I get the token in the API?
I have resolved this problem by using the aws-cognito-next library.
Following the documentation from https://www.npmjs.com/package/aws-cognito-next, I have created an auth utility:
import { createGetServerSideAuth, createUseAuth } from "aws-cognito-next";
import pems from "../../pems.json"
// create functions by passing pems
export const getServerSideAuth = createGetServerSideAuth({ pems });
export const useAuth = createUseAuth({ pems });
// reexport functions from aws-cognito-next
export * from "aws-cognito-next";
The pem file was generated by issuing the command (needless to say, you must configure an Amazon Cognito service first):
yarn prepare-pems --region <region> --userPoolId <userPoolId>
And finally, in the NextJs API:
import {getServerSideAuth} from "../../src/utils/AuthUtils"
export default async (req, res) => {
const initialAuth = getServerSideAuth(req)
console.log("initialAuth ", initialAuth)
if (initialAuth) {
res.status(200).json({status: 'success'})
} else {
res.status(400).json({status: 'fail'})
}
}
A simple method is to enable ssrContext in your app and Amplify will provide the user credentials to your api
on the frontend eg _app.tsx (or app.js)
import Amplify, { Auth, API } from "aws-amplify";
import awsconfig from "../src/aws-exports";
Amplify.configure({...awsconfig, ssr: true});
Then in the api you can simply get the currently authenticated cognito user
eg api/myfunction.tsx (or js)
import Amplify, { withSSRContext } from "aws-amplify";
import awsExports from "../../src/aws-exports";
Amplify.configure({ ...awsExports, ssr: true });
/* #returns <CognitoUser>,OR null if not authenticated */
const fetchAuthenticatedUser: any = async (req: NextApiRequest) => {
const { Auth } = withSSRContext({ req });
try {
let user = await Auth.currentAuthenticatedUser();
return user;
} catch (err) {
return null;
}
}

Angular 9 throw CORS error on loading page

I am working on Angular 9 application with .NET CORE Web API 3.1 application. I configure Angular client App to authenticate using Auth 2.0 Azure B2C and using angular-oauth2-oidc library in Angular. I am getting CORS Policy error soon I call http://localhost:4200
I can successfully call AD B2C via Postman and get token
When click on Login button, I get following error
{"error":"invalid_request","error_description":"AADB2C90083: The request is missing required parameter: grant_type.\r\nCorrelation ID: xxxxxf7b-f507-48bc-884f-41xxxxxxxxxx\r\nTimestamp: 2020-05-08 09:21:41Z\r\n"}
component
import { Component } from '#angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
import { authConfig } from './auth.config';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Angular9B2CAuthApp';
constructor(private oauthService:OAuthService){
this.configureSingleSignOn();
}
configureSingleSignOn(){
this.oauthService.configure(authConfig);
this.oauthService.tokenValidationHandler = new JwksValidationHandler();
this.oauthService.loadDiscoveryDocumentAndTryLogin();
}
login(){
this.oauthService.initImplicitFlow();
}
logout(){
this.oauthService.logOut();
}
}
Auth.config
error after updating login url
You're setting the token endpoint (which does not support CORS and is not intented for SPA/Implicit Flow/GET calls thus the 400 status code) into your config loginUrl property. You have to set it to your user flow or policy authorize endpoint like this:
{
"loginUrl":"https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/oauth2/v2.0/authorize"
}

Response with status:0 for URL:null when i am making a rest from ios ionic app

I am making a rest call from ionic app and its working in android device but not in the ios device.
This is how i am making a rest call from my ionic service.
import { Http } from '#angular/http';
import { Injectable } from '#angular/core';
#Injectable()
export class loginService {
constructor(private http : Http){ }
getAllUsers(authData){
console.log(authData);
return this.http.post('http://Some IP add:8080/api/customerr/getUser', authData);
}
}
This is how I am receiving the data in my login.ts file
this.loginservice.getAllUsers(this.loginForm.value).subscribe((response) => {
this.loginResponse = response.json()
} (err)=>{
alert(err)
});
Finally… I solved this problem by changing the API URL call from "http://yourapiurl/" to "https://yourapiurl/" and That sounds good. Please try this one.
I got this from here,
Reference
Thank you.

Passing very large XML data as params in Angular 2 to Rails

I have a text area, where user can paste any XML. Then on click of a button, the XML is sent to the server to get the response. I find, this works perfectly with smaller XMLs. But, my issue is, when I send a large XML, the Rails server log simply says
!! Invalid
request
CODE
Provider.ts
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { HttpClientService } from './../services/httpclient.service';
#Injectable()
export class QuestWebServiceTestProvider {
constructor(private http: HttpClientService) {}
getResponseXML(params) {
return this.http.get('/api/v1/get_response_xml?request_xml=' + params["request_xml"]);
}
}
Component.ts (this passes the XML read from textarea to provider)
getResponse() {
let requestXml = this.requestXmlElement.nativeElement.value.trim();
if(requestXml.length > 0) {
let requestXmlJson = encodeURI(requestXml);
this.<provider>.getResponseXML({request_xml: requestXmlJson).subscribe(
data => {
console.log(data);
}
)
}
}
What is the best way to send larger XMLs?
Sorry, for the typo in the question. I actually use POST request.
Thanks Pavel Mikhailyuk for pointing it.
This is how I fixed it:
Instead of framing the query params manually as:
...get_response_xml?request_xml=' + params["request_xml"]
I pass the XML as options to HTTP POST:
let options = {request_xml: params["request_xml"] };
return this.http.post('...get_response_xml?, options);
This seemed to work !!!

Resources