Authentication with separated client and server
Asked Answered
S

4

9

I have created web application in angular 2 for the client side and NodeJS with express framework for the server-side.

For the client side, I generated the project with angular-cli which runs on a lite-server, so my client and server are running on 2 different services.

I want to integrate ADFS authentication. To implement the authentication, I am using passport-saml package. There is a middleware in my server-side API which requires a user to authenticate.

The authentication process works fine when reaching the server directly (without the client).

However, I fail to access the API through the @angular/http. I tried a simple GET request from the server (with the middleware in the end-point) and as a result I am getting the authentication page without redirection (I don't think it's the core problem, but the actual implementation is).

How should I properly implement the authentication when using separate services to the server and the client?

Spinifex answered 19/2, 2017 at 9:55 Comment(1)
@Ron537_ did you got any useful solution?Stramonium
C
2

Hi I was also facing the same issue my angular project was hosted on 4200 port. and my node on 3000 port. Its difficult to implement passport when we have 2 ports running.

step 1 make angular project static by doing an ng build to public folder . make sure angular-cli.json has *"outDir": "../public",*

step 2 Now we can use the same node port to access angular roots please add below code in your node app.js

var path = require('path');
  // Set Static Folder
app.use(express.static(path.join(__dirname, 'public')));
app.get('*', function(req, res) {
     res.sendFile(path.join(__dirname, 'public/index.html'));
});

This will enable your angular project accessible through node port.

step 3: Now we can add the passport login button in the UI and give the url <a href="/passport/auth/twitter">twitter</a>

THIS IS not explanatory means feel to ask me the doubts.

Clayborn answered 1/10, 2017 at 3:34 Comment(2)
Your solution would work, but my goal was to separate the client from the server and not combine them together on the same port. What I did is I used iframe to connect the client directly to the server's authentication page i.e /auth/login and then after the server successfully authenticated the user, I used EJS engine to render the user data in the page and passed it to the client (outside the iframe) with parent.postMessage. This way I can keep client and server on different ports and archive authentication with passport.js.Spinifex
I am also looking for separate client and server. Combining client and server on the same port is not a solution for me too.Stramonium
R
0

You are not giving much detail on what the failed response was when the client did the GET to the server. Was it a 400? 401? 404? 500? did you get a CORS error?

Why are you using GET for your login endpoint. You should be POSTing credentials right in the POST payload?

Anyway, in your angular2 code you should have an auth service with a login method. The login method should do something like ..

login(credentials) {
    return http.post(your_server_url, payload);
}

you can then subscribe to the Observable returned by the login method and if all is good router.navigate to the home page or if it did not go well display login error messages.

Roybal answered 26/3, 2017 at 4:9 Comment(0)
S
0

Set separate urls for ui and server in ..src/environments/environment.ts

 export const environment = {
  production: false,
  BASE_URL: 'http://localhost:4200',
  API_BASE_URL: 'http://localhost:5000',
};

In node app.js

    app.use('/', express.static('public'));
  app.get('*', function (req, res) {
    res.sendFile(path.join(process.cwd(), 'public', 'index.html'));
  });
Starvation answered 12/12, 2017 at 7:35 Comment(5)
Will passport.js treat it as the same domain? and what about session.Stramonium
I am not sure of it. I have used it in my application with Angular2 and Node.js which is working well.Starvation
Have you written any code for allowing cross-domain requests (CORS) in your Express app.js file?Stramonium
app.use(function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE'); res.setHeader('Access-Control-Max-Age', 60 * 60 * 24 * 7); next(); });Starvation
I don't think it will solve the real problem. The problem is that Express-session works fine in the same domain (client 3000 and server also 3000) but in the different domain (client 4200 and server 3000) it doesn't work well. It generates a new session on each new request and doesn't persist the same session for user authentication.Stramonium
P
0

In your development environment, you should accomplish this by instructing your Angular CLI to proxy all requests to a backend server running on a separate port whenever you run "ng serve". Angular has good documentation on how to do this at https://angular.io/guide/build#proxying-to-a-backend-server. This will make your development process much faster, because you will not need to manually build your Angular application to test every code change.

When a production build is run, Angular will move the distributed files to the location specified in the "outputPath" property of Angular.json (by default set to "dist/<projectName>"). Your main production server will serve them appropriately from there as mentioned by @Lijo in their answer.

Puckett answered 28/12, 2021 at 0:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.