import { HttpRequest, HttpHandler, HTTP_INTERCEPTORS } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Observable } from "rxjs";
import { TokenService } from "./token.service";
#Injectable({
providedIn: 'root'
})
export class InterceptorService {
constructor(private tokenService: TokenService) {
intercep(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
let intReq = req;
const token = this.tokenService.getToken();
if (token != null) {
intReq = req.clone({
headers: req.headers.set('Authorization','Bearer'+token)
});
}
return next.handle(intReq);
}
}
export const interceptorProvider =[{
provide: HTTP_INTERCEPTORS,
useClass: InterceptorService,
multi: true
}];
//No reconoce y marca error en interceptor, req, token, next //todos errores no reconoce ni me dice de importar nada //
Related
I've tried to implement an oauth method using GraphQL with Google auth and for some reason I'm getting the following error
"res.setHeader is not a function" from within the authenticate method in Google Strategy
I've used passport-google-oauth20 strategy
this is my google-auth.guard.ts
import { ExecutionContext, Injectable } from '#nestjs/common';
import { GqlExecutionContext } from '#nestjs/graphql';
import { AuthGuard } from '#nestjs/passport';
#Injectable()
export class GoogleAuthGuard extends AuthGuard('google') {
getRequest(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
const gqlReq = ctx.getContext().req;
if (gqlReq) {
const { token } = ctx.getArgs();
gqlReq.body = { token };
return gqlReq;
}
return context.switchToHttp().getRequest();
}
}
this is my google.strategy.ts
import { PassportStrategy } from '#nestjs/passport';
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
import { Injectable, UnauthorizedException } from '#nestjs/common';
import { Profile } from 'passport';
#Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor() {
super({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_SECRET,
callbackURL: process.env.GOOGLE_REDIRECT_URL,
prompt: 'consent',
scope: ['email', 'profile'],
})
}
async validate(
accessToken: string,
refreshToken: string,
profile: Profile,
done: VerifyCallback,
): Promise<any> {
if (!profile) {
return done(new UnauthorizedException(), false);
}
return done(null, profile);
}
}
it's important to point out that since my app is a react SPA, the callbackURL value is the main page of the client and not another path in the server.
and the resolver which I intend to use to generate a jwt token and a refresh token, but the code never gets to this part due to the error in the strategy
#UseGuards(GoogleAuthGuard)
#Query(() => LoginResponseApi)
async googleLogin(
#Args({ name: 'token', type: () => String }) token: string,
#Req() req,
#Context() context
): Promise<LoginResponseApi> {
const res: Response = context.req.res;
const loginResponse: any = await this.authService.googleLogin(req)
const jwtToken = this.authService.createRefreshToken(loginResponse.user)
if (loginResponse.accessToken)
this.authService.sendRefreshToken(res, jwtToken)
return loginResponse;
}
I have a hard time passing the right angular request to the header. This is my service:
import { Injectable } from '#angular/core';
import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpHeaders }
from '#angular/common/http';
import { Utente } from '../model/Utente ';
import { Prodotto } from '../model/Prodotto ';
import { OktaAuthService } from '#okta/okta-angular';
import { Observable, from } from 'rxjs';
import { Carrello } from '../model/Carrello ';
import { userInfo } from 'node:os';
import { getLocaleCurrencyCode } from '#angular/common';
const headers = new HttpHeaders().set('Accept', 'application/json');
#Injectable({
providedIn: 'root'
})
export class HttpClientService {
constructor(
private httpClient:HttpClient, private oktaAuth:OktaAuthService ) {}
getCarr(){
return this.httpClient.get<Carrello[]>('http://localhost:8080/prodotti/utente/vedicarrelloo', {headers} );
}
}
This is my spring method:
#Transactional(readOnly = true)
public List<Carrello> getCarrello(#AuthenticationPrincipal OidcUser utente){
Utente u= utenteRepository.findByEmail(utente.getEmail());
return carrelloRepository.findByUtente(u);
}
In console I get this error (error 500):
https://i.stack.imgur.com/BiONS.png
this error corresponds in my console to "java.lang.NullPointerException: null.
But if I access localhost: 8080, I can see the answer correctly, so I assume there is a problem in passing the request header in angular, can anyone tell me where am I wrong, please? I specify that I get this error only in the methods where the OidcUser is present, the rest works perfectly. Thank you!
You need to send an access token with your request. Like this:
import { Component, OnInit } from '#angular/core';
import { OktaAuthService } from '#okta/okta-angular';
import { HttpClient } from '#angular/common/http';
import sampleConfig from '../app.config';
interface Message {
date: string;
text: string;
}
#Component({
selector: 'app-messages',
templateUrl: './messages.component.html',
styleUrls: ['./messages.component.css']
})
export class MessagesComponent implements OnInit {
failed: Boolean;
messages: Array<Message> [];
constructor(public oktaAuth: OktaAuthService, private http: HttpClient) {
this.messages = [];
}
async ngOnInit() {
const accessToken = await this.oktaAuth.getAccessToken();
this.http.get(sampleConfig.resourceServer.messagesUrl, {
headers: {
Authorization: 'Bearer ' + accessToken,
}
}).subscribe((data: any) => {
let index = 1;
const messages = data.messages.map((message) => {
const date = new Date(message.date);
const day = date.toLocaleDateString();
const time = date.toLocaleTimeString();
return {
date: `${day} ${time}`,
text: message.text,
index: index++
};
});
[].push.apply(this.messages, messages);
}, (err) => {
console.error(err);
this.failed = true;
});
}
}
On the Spring side, if you want it to accept a JWT, you'll need to change to use Jwt instead of OidcUser. Example here.
#GetMapping("/")
public String index(#AuthenticationPrincipal Jwt jwt) {
return String.format("Hello, %s!", jwt.getSubject());
}
I need to add headers to my graphql requests with angular with subscriptions. but I didn't find any way. headers will be added if I only used headers without subscriptions. Also, subscriptions will works if I didn't add headers. But with both, it won't work. here is my code
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { ApolloModule, Apollo, APOLLO_OPTIONS } from 'apollo-angular';
import { HttpLinkModule, HttpLink } from 'apollo-angular-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloLink, split } from 'apollo-link';
import { setContext } from 'apollo-link-context';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';
const uri = 'http://localhost:5000/graphql';
export function provideApollo(httpLink: HttpLink) {
const basic = setContext((operation, context) => ({
headers: {
Accept: 'charset=utf-8'
}
}));
// Get the authentication token from local storage if it exists
const token = localStorage.getItem('token');
const auth = setContext((operation, context) => ({
headers: {
Authorization: `Bearer ${token}`
},
}));
const subscriptionLink = new WebSocketLink({
uri:
'ws://localhost:5000/graphql',
options: {
reconnect: true,
connectionParams: {
authToken: localStorage.getItem('token') || null
}
}
});
const link = split(({ query }) => {
const { kind } = getMainDefinition(query);
return kind === 'OperationDefinition';
}, subscriptionLink, ApolloLink.from([basic, auth, httpLink.create({ uri })]));
// const link = ApolloLink.from([basic, auth, httpLink.create({ uri }), subscriptionLink]);
const cache = new InMemoryCache();
return {
link,
cache
};
}
#NgModule({
exports: [
HttpClientModule,
ApolloModule,
HttpLinkModule
],
providers: [{
provide: APOLLO_OPTIONS,
useFactory: provideApollo,
deps: [HttpLink]
}]
})
export class GraphQLModule { }
in here headers will not be added. Any Solutions?
This is the solution that I found.
Import below code to your app.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { HttpHeaders } from '#angular/common/http';
import { APOLLO_OPTIONS } from "apollo-angular";
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';
import { split } from 'apollo-link';
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from 'apollo-angular-link-http';
#NgModule({
imports: [
CommonModule,
],
providers: [
{
provide: APOLLO_OPTIONS,
useFactory(httpLink: HttpLink) {
const http = httpLink.create({
uri: 'http://localhost/v1/graphql',
headers: new HttpHeaders({
"x-hasura-admin-secret": "mysecretkey"
})
})
const ws = new WebSocketLink({
uri: `ws://localhost/v1/graphql`,
options: {
reconnect: true,
connectionParams: {
headers: {
"x-hasura-admin-secret": "mysecretkey"
}
}
}
});
const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
ws,
http,
);
return {
link,
cache: new InMemoryCache(),
};
},
deps: [HttpLink],
},
]
})
export class GraphqlModule { }
import { NgModule } from "#angular/core";
import { HttpClientModule, HttpHeaders } from "#angular/common/http";
import { ApolloModule, Apollo, APOLLO_OPTIONS } from "apollo-angular";
import { HttpLinkModule, HttpLink } from "apollo-angular-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloLink, split, from } from "apollo-link";
import { setContext } from "apollo-link-context";
import { WebSocketLink } from "apollo-link-ws";
import { getMainDefinition } from "apollo-utilities";
import ApolloClient from "apollo-client";
const uri = "http://localhost:5000/graphql";
const subscriptionLink = new WebSocketLink({
uri: "ws://localhost:5000/graphql",
options: {
reconnect: true,
connectionParams: {
authToken: localStorage.getItem("token") || null,
},
},
});
const authMiddleware = new ApolloLink((operation: any, forward: any) => {
operation.setContext({
headers: new HttpHeaders().set(
"Authorization",
`Bearer ${localStorage.getItem("token")}` || null,
),
});
return forward(operation);
});
export function createApollo(httpLink: HttpLink) {
return {
link: from([
authMiddleware,
split(
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === "OperationDefinition" && operation === "subscription";
},
subscriptionLink,
httpLink.create({
uri: "http://localhost:5000/graphql",
}),
),
]),
cache: new InMemoryCache(),
};
}
#NgModule({
exports: [HttpClientModule, ApolloModule, HttpLinkModule],
providers: [
{
provide: APOLLO_OPTIONS,
useFactory: createApollo,
deps: [HttpLink],
},
],
})
export class GraphQLModule {}
I've followed the tutorial from https://tutorialedge.net/typescript/angular/angular-websockets-tutorial/
as I'm trying to setup a websocket connection but I'm getting an error after the socket gets connected. The error says "Error during WebSocket handshake: Unexpected response code: 502"
I've followed the tutorial and followed the steps but i still get the error after the socket gets connected.
websocket.service.ts
import { Injectable } from '#angular/core';
import * as Rx from 'rxjs/Rx';
#Injectable({
providedIn: 'root'
})
export class WebsocketService {
constructor() { }
private subject: Rx.Subject<MessageEvent>;
public connect(url): Rx.Subject<MessageEvent> {
if (!this.subject) {
this.subject =
this.create('ws://61c725fa.ngrok.io/auth/forgot_password/');
console.log("Successfully connected: " + url);
}
return this.subject;
}
private create(url): Rx.Subject<MessageEvent> {
let ws = new WebSocket(url);
let observable = Rx.Observable.create((obs:
Rx.Observer<MessageEvent>) => {
ws.onmessage = obs.next.bind(obs);
ws.onerror = obs.error.bind(obs);
ws.onclose = obs.complete.bind(obs);
return ws.close.bind(ws);
});
let observer = {
next: (data: Object) => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify(data));
}
}
};
return Rx.Subject.create(observer, observable);
}
}
notifier.service.ts
import { Injectable } from '#angular/core';
import { Observable, Subject } from "rxjs-compat/Rx";
import { WebsocketService } from "./websocket.service";
import { map } from 'rxjs/operators';
let ws_scheme = window.location.protocol == "https:" ? "wss" :
"ws";
let ws_path = ws_scheme + '://' +"61c725fa.ngrok.io" +
"/auth/forgot_password/";
const URL = ws_path;
export interface Message {
username: string;
}
#Injectable({
providedIn: 'root'
})
export class NotifierService {
public messages: Subject<Message>;
constructor(wsService: WebsocketService) {
this.messages = <Subject<Message>>wsService
.connect(URL).pipe(map((response: MessageEvent): Message => {
let data = JSON.parse(response.data);
return {
username: data.message
}
}));
}
}
component.ts
import { Component } from '#angular/core';
import { NotifierService } from './notifier.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'ang-socket';
constructor(private notifier:NotifierService){
notifier.messages.subscribe(msg=>{
console.log("response from websocket:" + msg);
})
}
private message = {
username: "abc#gmail.com"
};
sendMsg() {
console.log("new message from client to websocket: ",
this.message);
this.notifier.messages.next(this.message);
this.message.username = "";
}
}
I would like to fix this issue. Great if someone helps.
I am building a basic CRUD application in Angular2. However I am having some issues while running tests of components.
Component Code:
///<reference path="../../node_modules/angular2/typings/browser.d.ts"/>
import { Component, OnInit } from 'angular2/core';
import { RouteParams, Router, ROUTER_DIRECTIVES } from 'angular2/router';
import { EmployeeEditFormComponent } from './employee-edit-form.component';
import { EmployeeDetailServiceComponent } from '../services/employee-detail-service.component';
import { EmployeeDeleteServiceComponent } from '../services/employee-delete-service.component';
#Component({
selector: 'employee-detail',
templateUrl: 'src/pages/employee-detail.component.html',
providers: [
EmployeeDetailServiceComponent,
EmployeeDeleteServiceComponent
],
directives: [ ROUTER_DIRECTIVES, EmployeeEditFormComponent ]
})
export class EmployeeDetailComponent implements OnInit {
public currentEmployee;
public errorMessage: string;
constructor(
private _router: Router,
private _routeParams: RouteParams,
private _detailService: EmployeeDetailServiceComponent,
private _deleteService: EmployeeDeleteServiceComponent
){}
ngOnInit() {
let id = parseInt(this._routeParams.get('id'));
this._detailService.getEmployee(id).subscribe(
employee => this.currentEmployee = employee,
error => this.errorMessage = <any>error
);
}
deleteHandler(id: number) {
this._deleteService.deleteEmployee(id).subscribe(
employee => this.currentEmployee = employee,
errorMessage => this.errorMessage = errorMessage,
() => this._router.navigate(['EmployeeList'])
)
}
}
Spec Code:
/// <reference path="../../typings/main/ambient/jasmine/jasmine.d.ts" />
import {
it,
describe,
expect,
TestComponentBuilder,
injectAsync,
setBaseTestProviders,
beforeEachProviders
} from "angular2/testing";
import {
Response,
XHRBackend,
ResponseOptions,
HTTP_PROVIDERS
} from "angular2/http";
import {
MockConnection,
MockBackend
} from "angular2/src/http/backends/mock_backend";
import {
TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS
} from "angular2/platform/testing/browser";
import {
Component,
provide
} from "angular2/core";
import {
RouteParams
} from 'angular2/router';
import 'rxjs/Rx';
import { Employee } from '../models/employee';
import { EmployeeDetailComponent } from './employee-detail.component';
import { EmployeeEditFormComponent } from './employee-edit-form.component';
import { EmployeeDetailServiceComponent } from '../services/employee-detail-service.component';
import { EmployeeDeleteServiceComponent } from '../services/employee-delete-service.component';
class MockDetailService{
public getEmployee (id: number) {
return new Employee(1, "Abhinav Mishra");
}
}
class MockDeleteService{
public deleteEmployee (id: number) {
return new Employee(1, "Abhinav Mishra");
}
}
describe('Employee Detail Component Tests', () => {
setBaseTestProviders(
TEST_BROWSER_PLATFORM_PROVIDERS,
TEST_BROWSER_APPLICATION_PROVIDERS
);
beforeEachProviders(() => {
return [
HTTP_PROVIDERS,
provide(XHRBackend, {useClass: MockBackend}),
provide(RouteParams, { useValue: new RouteParams({ id: '1' }) }),
provide(EmployeeDetailServiceComponent, {useClass: MockDetailService}),
provide(EmployeeDeleteServiceComponent, {useClass: MockDeleteService})
]
});
it('should render list', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
return tcb
.overrideProviders(EmployeeDetailComponent,
[
provide(EmployeeDetailServiceComponent, {useClass: MockDetailService}),
provide(EmployeeDeleteServiceComponent, {useClass: MockDeleteService})
]
)
.createAsync(EmployeeDetailComponent).then((componentFixture) => {
componentFixture.detectChanges();
expect(true).toBe(true);
});
}));
});
I keep getting following error:
Error: XHR error (404 Not Found) loading http://localhost:9876/angular2/router
at error (/home/abhi/Desktop/angular2-testing/node_modules/systemjs/dist/system.src.js:1026:16)
at XMLHttpRequest.xhr.onreadystatechange (/home/abhi/Desktop/angular2-testing/node_modules/systemjs/dist/system.src.js:1047:13)
at XMLHttpRequest.wrapFn [as _onreadystatechange] (/home/abhi/Desktop/angular2-testing/node_modules/angular2/bundles/angular2-polyfills.js:771:30)
at ZoneDelegate.invokeTask (/home/abhi/Desktop/angular2-testing/node_modules/angular2/bundles/angular2-polyfills.js:365:38)
at Zone.runTask (/home/abhi/Desktop/angular2-testing/node_modules/angular2/bundles/angular2-polyfills.js:263:48)
at XMLHttpRequest.ZoneTask.invoke (/home/abhi/Desktop/angular2-testing/node_modules/angular2/bundles/angular2-polyfills.js:431:34)
Would be great to have some feedbacks.