I am following the integration setup of https://github.com/loopbackio/loopback-next/tree/master/examples/passport-login
However, this example uses an Express server with nextjs integrated into the project.
In my case I am useing ReactJS to request an Apple ID Login:
const loginSocial = (provider: string) => {
const url = `${process.env.REACT_APP_API_URL}/auth/thirdparty/${provider}`;
fetch(url).then((res) => {
return res.json()
}).then((e) => {
window.open(e.redirectUrl, '_blank', 'height=600,width=400');
}).catch((e) => {
console.warn(e);
})
}
My controller looks like this:
import {authenticate, AuthenticationBindings} from '@loopback/authentication';
import {inject} from '@loopback/core';
import {get, param, post, Request, RequestWithSession, Response, RestBindings} from '@loopback/rest';
import {SecurityBindings, UserProfile} from '@loopback/security';
import {oAuth2InterceptExpressMiddleware} from '../authentication-interceptors';
import passport from "passport";
/**
* Login controller for third party oauth provider
*
* This controller demonstrates using passport strategies both as express middleware and as an independent strategy
*
* The method loginToThirdParty uses the @authenticate decorator to plugin passport strategies independently
* The method thirdPartyCallBack uses the passport strategies as express middleware
*/
export class Oauth2Controller {
constructor() {}
@authenticate('oauth2')
@get('/auth/thirdparty/{provider}')
/**
* This method uses the @authenticate decorator to plugin passport strategies independently
*
* Endpoint: '/auth/thirdparty/{provider}'
* an endpoint for api clients to login via a third party app, redirects to third party app
*/
loginToThirdParty(
@param.path.string('provider') provider: string,
@inject(AuthenticationBindings.AUTHENTICATION_REDIRECT_URL)
redirectUrl: string,
@inject(AuthenticationBindings.AUTHENTICATION_REDIRECT_STATUS)
status: number,
@inject(RestBindings.Http.RESPONSE)
response: Response,
) {
return {redirectUrl: redirectUrl};
}
@oAuth2InterceptExpressMiddleware()
@get('/auth/thirdparty/{provider}/callback')
/**
* This method uses the passport strategies as express middleware
*
* Endpoint: '/auth/thirdparty/{provider}/callback'
* an endpoint which serves as a oauth2 callback for the thirdparty app
* this endpoint sets the user profile in the session
*/
async thirdPartyCallBack(
@param.path.string('provider') provider: string,
@inject(SecurityBindings.USER) user: UserProfile,
@inject(RestBindings.Http.REQUEST) request: RequestWithSession,
@inject(RestBindings.Http.RESPONSE) response: Response,
) {
const profile = {
...user.profile,
};
request.session.user = profile;
response.redirect('/auth/account');
return response;
}
@oAuth2InterceptExpressMiddleware()
@post('/auth/thirdparty/{provider}/callback')
/**
* This method uses the passport strategies as express middleware
*
* Endpoint: '/auth/thirdparty/{provider}/callback'
* an endpoint which serves as a oauth2 callback for the thirdparty app
* this endpoint sets the user profile in the session
*/
async thirdPartyCallBackPost(
@param.path.string('provider') provider: string,
// @inject(SecurityBindings.USER) user: UserProfile,
@inject(RestBindings.Http.REQUEST) request: Request,
@inject(RestBindings.Http.RESPONSE) response: Response,
) {
console.log('reached callback');
console.log(request.body);
passport.authenticate('apple', function(err: any, user: any, info: any) {
console.log(user);
})(request, response);
// return request;
}
}
It turns out that the Apple callback is using a POST method, so I added this to the controller. Note that in the example in the repository there is only a GET method, (I am not sure why that is the case).
However, it only reaches my POST endpoint if I remove @oAuth2InterceptExpressMiddleware(). If I include the decorator nothing happens, and the Apple login windo (which was opened from my ReactJS app) remains open and simply redirects to the login screen. But if I remove the decorator I miss the entire middleware setup as it was intended within the example application.
So my questions are:
- How do I successfully integrate passport-apple into my Loopback 4 API?
- How is the Apple login window auto-closed after login has been completed?
- Why does the example repo have a GET endpoint while Apple is clearly using POST method?
Hi, you have a wrong tag.
[loopback]
should be [loopbackjs
]