Steam Authentication with Angular

I try to authenticate using Steam from the Angular homepage, but whenever I click on a button (which has a (click) event pointing to the login() function in the AppComponent ), instead of redirecting to the Steam Page, the current page is updated, and Nothing happens.

This is the server side code:

 'use strict'; const express = require('express'); const app = express(); const server = require('http').createServer(app); const io = require('socket.io').listen(server); const jwt = require('express-jwt'); const cors = require('cors'); const passport = require('passport'); const SteamStrategy = require('passport-steam').Strategy; const mongoose = require('mongoose'); app.use(cors()); mongoose.connect('mongodb://localhost:27017/database_test'); passport.serializeUser((user, done) => { done(null, user); }); passport.deserializeUser((obj, done) => { done(null, obj); }); passport.use(new SteamStrategy({ returnURL: 'http://localhost:3000/auth/steam/return', realm: 'http://localhost:3000', apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx' }, (identifier, profile, done) => { process.nextTick(() => { profile.identifier = identifier; return done(null, profile); }); } )); app.use(passport.initialize()); app.use(passport.session()); app.get('/auth/steam', passport.authenticate('steam', { failureRedirect: 'http://localhost:4200/home' }), (req, res) => { res.json({"success": true, "res": res}); } ); app.get('/auth/steam/return', passport.authenticate('steam', { failureRedirect: 'http://localhost:4200/home' }), (req, res) => { res.json({"success": true, "res": res}); } ); server.listen(3000, () => { console.log('Backend listening on port 3000.'); }); 

This is an AuthenticationService :

 import { Injectable } from '@angular/core'; import { Http, Headers, RequestOptions } from '@angular/http'; import { Observable } from 'rxjs'; import { JwtHelper, tokenNotExpired } from 'angular2-jwt'; import 'rxjs/add/operator/map'; @Injectable() export class AuthenticationService { domain = 'http://localhost:3000'; constructor(private http: Http) { } login() { return this.http.get(this.domain + '/auth/steam').map(res => res.json()); } } 

This is the AppComponent :

 import { Component } from '@angular/core'; import { AuthenticationService } from './authentication.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [ AuthenticationService ] }) export class AppComponent { constructor(private authService: AuthenticationService) { } login(): void { this.authService.login().subscribe(data => { alert(data); }); } } 

Both servers work (Angular and Node).

Edit: I added a button instead of a link, and the log showed me that there is a policy error of the same origin .

+5
source share
4 answers

Simply put, you cannot redirect your Angular service to your backend => steam => backend callback url. You must redirect the user there.

So instead of calling authService.login() just add a direct link, as said elsewhere. I do not see the first link in your internal code, but the interface code offers /auth/steam , as in the SteamStrategy docs.

So step 1 is this:

 // change the login() method on AuthService login() { window.location.href = "http://localhost:3000/auth/steam"; } 

(You will want to migrate this URL from environment or a little later).

What is happening now:

  • Browser goes to localhost:3000/auth/steam
  • Node redirects browser to openId password
  • Steam, after successful login and authorization, redirects back to http://localhost:3000/auth/steam/return

What will happen next?

  • First, save the profile data in the Passport strategy for the user profile, or at least for the user session.
  • redirect the user back to the Angular application. Something like that:

    res.redirect('/public/#/authcallback ) `

(Using HashLocationStrategy here so you can clearly see where I am redirecting you.)

  • Now your Angular /authcallback route should most likely hit the endpoint again in order to receive auth data before doing its own redirects.

Alternative:

Now this last part can be done differently. You could do something like redirect from node back to the index or to any source route (you can add them as parameters, etc.). Then use the Angular service, which always checks with the backend if there is auth data.

Or you could use the node backend to embed information in Angular index.html or any other page that you use. You know, old data on the server side enters data, perhaps in a script tag with something like ejs or jade . It will be faster, but I still won’t trust him blindly on the client (or server) and will double-check, possibly in the background.

+2
source

What you do in your code causes a GET request to your own server. I do not see page redirections at all.

If you want to redirect the user to an external website, you need to send him there:

From the HTML file:

 <a href="http://example.com">Link to steam</a> 

From the .ts component file:

 window.location.href = 'http://www.example.com' 

If you want to redirect the user to another page of your website, you need to use Angular Router:

From the HTML file:

 <a routerLink="/component-one">Component One</a> 

From the .ts component file:

 this.router.navigate(['/component-one']); 

So now you become a component:

 import { Component } from '@angular/core'; import { AuthenticationService } from './authentication.service'; import { Router } from '@angular/router'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], providers: [ AuthenticationService ] // This should be provided by the module, not the component }) export class AppComponent { constructor(private authService: AuthenticationService, private router: Router) { } login(): void { this.authService.login().subscribe(data => { alert(data); this.router.navigate('/to-some-page'); }); } } 

Additional examples can be found using a simple Google search , as shown below https://coryrylan.com/blog/introduction-to-angular-routing

+1
source

As far as I see, you never direct the user to the steam page. Your comment on klong: "Redirecting through Passport." It can be, however you never send the user to a certain page. You simply create the GET request form that you use.

About a policy error of the same origin. I assume this is caused by a passport because you use Cors on your express server. I believe that the best solution would be to create a simple proxy. If you use the CLI, you can use this example .

+1
source

First of all, you are not sending your login request for a backend expression. You must send your request to enter oidc authorize endpoint passwords. See what Steam says:

When using OpenID, the user runs in a web browser on a third-party website. When a user wants to log in / link their account with this site using OpenID, the site will direct the user to the login form on the Steam community website. After a user has entered his Steam login credentials, the user's web browser is automatically redirected back to a third-party site with some additional OpenID data added to the return URL. The site’s OpenID library can then use this data to validate and retrieve a custom SteamID.

It's called Oidc, and you are lucky to have two good libraries for Angular. This (recommended) and This .

What your express server needs to do is check the token received from your angular client before requesting. I am not very familiar with the expression, but I am sure that there are at least a few libraries for checking the token.

You also need to do more research on this topic.

+1
source

Source: https://habr.com/ru/post/1274318/


All Articles