Signin with apple with passport-apple library not returning id_token in nestjs - nestjs

I am setting up Apple Login with the "passport-apple" library using NestJS. The first login returns a data object with "state," "code," and "user," but no id_token.
Subsequent logins return data objects containing only "state" and "code."
I understand that Apple does not return a user object in the subsequent login, but "code" and "state" are not unique to the user as the value returned for "state" and "code" is different at any login request. Now there is no way for me to identify the user each time the user makes a login request with Apple.
below is my strategy configuration:
import { Inject, Injectable } from '#nestjs/common';
import { ConfigService } from '#nestjs/config';
import { PassportStrategy } from '#nestjs/passport';
import { Strategy } from 'passport-apple';
import { readFileSync } from 'fs';
#Injectable()
export class AppleStrategy extends PassportStrategy(Strategy, 'apple') {
constructor(configService: ConfigService) {
super({
clientID: configService.get<string>('APPLE_CLIENT_ID'),
teamID: configService.get<string>('APPLE_TEAM_ID'),
keyID: configService.get<string>('APPLE_KEY_ID'),
key: readFileSync(
__dirname + '/../../../apple_secret/apple_secret_key.p8',
),
callbackURL: configService.get<string>('APPLE_CALLBACK_URL'),
passReqToCallback: false,
response_type: 'code id_token',
scope: ['name', 'email'],
});
}
}
My first login response body:
{
"state": ".......",
"code": "..............................................",
"user": "{"name":{"firstName":"First_Name","lastName":"Last_Name"},"email":"Email"}"
}
My subsequent respnse body:
{
"state": ".......",
"code": ".............................................."
}

Related

How can I pass header parameter for ando client application in apollo server?

I am having trouble while trying to use custom header parameter in apollo server. I have an apollo server as below:
import { ApolloServer } from 'apollo-server-lambda'
import { ApolloGateway, IntrospectAndCompose, GraphQLDataSourceProcessOptions, RemoteGraphQLDataSource } from '#apollo/gateway'
import { ApolloServerPluginLandingPageGraphQLPlayground } from 'apollo-server-core'
import { GraphQLRequest } from 'apollo-server-types'
import { SignatureV4 } from '#aws-sdk/signature-v4'
import { Sha256 } from '#aws-crypto/sha256-js'
import { OutgoingHttpHeader } from 'http'
import { defaultProvider } from '#aws-sdk/credential-provider-node'
import { HttpRequest } from '#aws-sdk/protocol-http'
class AuthenticatedDataSource extends RemoteGraphQLDataSource {
/**
* Adds the necessary IAM Authorization headers for AppSync requests
* #param request The request to Authorize
* #returns The headers to pass through to the request
*/
private async getAWSCustomHeaders(request: GraphQLRequest): Promise<{
[key: string]: OutgoingHttpHeader | undefined
}> {
const { http, ...requestWithoutHttp } = request
if (!http) return {}
const url = new URL(http.url)
//check local env
if(url.host.match(/localhost:20002/)) return {'x-api-key':'da2-fakeApiId123456'}
// If the graph service is not AppSync, we should not sign these request.
if (!url.host.match(/appsync-api/)) return {}
const httpRequest = new HttpRequest({
hostname: url.hostname,
path: url.pathname,
method: http.method,
headers: {
Host: url.host,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestWithoutHttp),
})
const signedRequest = await new SignatureV4({
region: 'eu-west-1',
credentials: defaultProvider(),
service: 'appsync',
sha256: Sha256,
}).sign(httpRequest)
return signedRequest.headers || {}
}
/**
* Customize the request to AppSync
* #param options The options to send with the request
*/
public async willSendRequest({ request, context }: GraphQLDataSourceProcessOptions) {
const customHeaders = await this.getAWSCustomHeaders(request)
if (customHeaders) {
Object.keys(customHeaders).forEach((h) => {
request.http?.headers.set(h, customHeaders[h] as string)
})
}
// context not available when introspecting
if (context.event)
Object.keys(context.event.requestContext.authorizer.lambda).forEach((h) => {
request.http?.headers.set(h, context.event.requestContext.authorizer.lambda[h] as string)
})
}
}
const server = new ApolloServer({
gateway: new ApolloGateway({
buildService({ url }) {
return new AuthenticatedDataSource({ url })
},
supergraphSdl: new IntrospectAndCompose({
subgraphs: [
{ name: 'CONFIGURATIONSERVICE', url: process.env.CONFIGURATION_SERVICE_API_URL }
]
})
}),
debug: true,
context: ({ event, context, express}) => ({
headers: event.headers,
functionName: context.functionName,
event,
context,
expressRequest: express.req,
}),
introspection: true,
plugins: [ApolloServerPluginLandingPageGraphQLPlayground()],
})
exports.handler = server.createHandler({
expressGetMiddlewareOptions: {
cors: {
origin: '*',
}
}
})
When I try to execute configurationservice via playground on port 3000, I realized that I do not x-api-key header parameter and therefore I get 401 authorization. I do not understand the reason of missing header parameter that I already added in the codebase and any help would be appreciated. Thank you!
Ok I noticed that I can also add header parameters via playground application. Now it returns no authorization error.

When i am trying fetch api from node js it is not working

import React, { useCallback, useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { useAppContext } from "./context/appContext";
import Video from "twilio-video";
import Room from "./components/Room/Room";
import { Home, Header } from "./components/index";
app.post("/video/token", (req, res) => {
const identity = req.body.identity;
const room = req.body.room;
const token = videoToken(identity, room, config);
sendTokenResponse(token, res);
});
In the above section i made api endpoint in node js /video/token but when i fetch it in React js it's give an error
const data = await fetch("/video/token", {
method: "POST",
body: JSON.stringify({
identity: username,
room: roomName,
}),
headers: {
"Content-Type": "application/json",
},
}).then((res) => res.json());
And the above code is fetching the api and it is returning Promise Unexpected token < at JSON position 0
import React, { useCallback, useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { useAppContext } from "./context/appContext";
import Video from "twilio-video";
import Room from "./components/Room/Room";
import { Home, Header } from "./components/index";
app.post("/video/token", (req, res) => {
const identity = req.body.identity;
const room = req.body.room;
const token = videoToken(identity, room, config);
sendTokenResponse(token, res);
});
You should use async and await together, not only await
async function sendData(){
await fetch("/video/token", {
method: "POST",
body: JSON.stringify({
identity: username,
room: roomName,
}),
headers: {
"Content-Type": "application/json",
},
}).then((res) => res.json());
}
this happens because you are trying to parse api response as json which is not a json
res.json()
here you should first check api response if its json or not.
Your issue is that your server is not responding with the correct response. That's why you're getting the error Unexpected token < at JSON position 0. The first character of the response is a < which implies that it is an HTML response, possibly with an error message within.
You should inspect the response that you are getting and see whether that tells you more about the error.
Also, make sure you are running the server side as well as running the client side. If the server isn't running, then you will definitely get errors from your fetch from the front-end.

Why Angular HTTP Post method Error: Cannot read property 'post' of undefined?

Angular HTTP Post method Error: Cannot read property 'post' of undefined.
I am trying to make my first http POST request.But it not working
export class RegisterComponent implements OnInit {
[x: string]: any;
firstnameControl = new FormControl(); //To get values
hide=true;
constructor( ) { }
ngOnInit(): void {
}
signup(){
//1.Collect Parameters
let body = new HttpParams({
fromObject:{
'firstname': this.firstnameControl.value,
}
});
//2.Send to URL
var url ="http://52.15.72.215:3000/api/user";
this.http.post(url ,body).subscribe(
( data: any) =>{
alert(data);
}
);
}
}
Why this post method not working
Nirodha, you need to put the provider in the constructor if you want to use http request:
Import the HttpClient:
import { HttpClient } from "#angular/common/http";
Put the HttpClient in the constructor:
constructor(private http: HttpClient){}
In your app.module.ts you need to put in the imports array it:
imports: [HttpClientModule]
And remember to import at the beginning of your code
import { HttpClientModule } from "#angular/common/http";

Error in React Native with Node.js backend

Error I am getting:
Nothing is displaying in the App screen but when I console log it's fetching data from the server in the terminal.
app screen feedscreen.js
import React, {useEffect, useState} from 'react';
import {ActivityIndicator, Text, View, FlatList} from 'react-native';
import stylesheet from '../src/styles/HomeStyle';
import AsyncStorage from '#react-native-community/async-storage';
const FeedScreen = props => {
const [text, setText] = useState('loading');
const Boiler = async () => {
const token = await AsyncStorage.getItem('token');
fetch('http://192.168.*.*:3000/post', {
headers: new Headers({
Authorization: 'Bearer ' + token,
}),
})
.then(res => res.json())
.then(data => {
console.log(data);
setText(data.text);
});
};
useEffect(() => {
Boiler();
}, []);
return (
<View style={stylesheet.container}>
<Text>{text}</Text>
</View>
);
};
export default FeedScreen;
My MongoDB table:
Console log:
LOG Running "AwesomeProject" with {"rootTag":61,"initialProps":{}}
LOG {"email": "test#demo.com", "name": "test demo"}
LOG [{"_id": "5e436d9112911336750a9fa6", "slug": "this-is-node-express-and-mongodb", "text": "This is node express and mongodb.", "user": [[Object]]}, {"_id": "5e3a976d5ca38b812a93d5fa", "slug": "this-is-the-social-network-api-which-is-build-on-top-of-node-express-and-mongodb", "text": "This is the social network api which is build on top of node express and mongodb.", "user": [[Object]]}, {"_id": "5e3a975d5ca38b812a93d5f9", "slug": "this-is-the-social-network-api-which-is-build-on-top-of-node-express-and-mongodb", "text": "This is the social network api which is build on top of node express and mongodb.", "user": [[Object]]}]

Problem using OAuth2 with Discord API on NestJS

I'm trying to create a custom API for Discord but for now i'm trying to setup OAuth2.
To make the necessary HTTP Requests i'm using the included HttpModule in NestJS which is axios, so in my servisse i'm defining a function to retrieve the code (previously sent by Discord) and finally get the access token, here's how it looks:
#Injectable()
export class AuthService {
constructor(private http: HttpService) {}
async validateToken(token: string) {
const data = {
client_id: [some thing],
client_secret: [some thing],
grant_type: 'authorization_code',
code: token,
redirect_url: encodeURI('https://49fe5ab2.ngrok.io/auth'),
scope: 'identify',
};
return await this.http
.post('https://discordapp.com/api/oauth2/token', null, { params: data, headers: {"Content-Type": "application/x-www-form-urlencoded"}})
.toPromise()
.then(resp => Logger.log(resp))
.catch(err => Logger.error(err));
}
}
And in the controller there's the route I set up for OAuth2 which is just a function
#Controller('auth')
export class AuthController {
constructor(private readonly AuthService: AuthService) {}
#Get()
responseRetrieve(#Req() request) {
return this.AuthService.validateToken(request.query.code);
}
}
What happen is that I only get 401 status codes which means that all my access are unauthorized. I already tried to pass the data as the request body and finally as it's currently is as params.
OBS: I know that I should've used environment variables for client id and for the client_secret but for now i'm trying to make this work.
I'm not getting what i'm doing wrong because the only that does not work is the axios POST request right after I receive the code (also refered as token in the service function

Resources