Аутентификация Steam с помощью Angular

Я пытаюсь выполнить аутентификацию в Steam с домашней страницы в Angular, но всякий раз, когда я нажимаю кнопку (которая имеет событие (click), указывающее на функцию login() в AppComponent), вместо перенаправления на страницу Steam текущая страница обновляется и ничего не происходит.

Это серверный код:

'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.');
});

Это 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());
  }

}

Это 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);
    });
  }

}

Оба сервера работают (Angular и Node).

Изменить: я добавил кнопку вместо ссылки, и журнал показал мне, что произошла ошибка с Политика одного и того же происхождения.


person Nikola Stojaković    schedule 25.12.2017    source источник
comment
Просто хотел добавить, спасибо за работу со Steam. Я в основном занимаюсь бизнесом/корпоративными вещами с Angular, и, судя по трафику StackOverflow, большинство других тоже. Вы отличаетесь тем, что делаете что-то, что, я полагаю, связано с играми! Удачи вам, сэр, и получайте удовольствие, а затем повеселитесь и для остальных :)   -  person Zlatko    schedule 04.01.2018


Ответы (4)


Проще говоря, вы не можете перенаправить свой сервис Angular на ваш backend=>steam=>backend callback url. Вы должны перенаправить пользователя туда.

Поэтому вместо вызова authService.login() просто добавьте прямую ссылку, как сказано в другом месте. Я не вижу первую ссылку в вашем внутреннем коде, но внешний код предлагает /auth/steam, как в документации SteamStrategy.

Итак, шаг 1 таков:

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

(Позже вы захотите взять этот URL-адрес из environment или чего-то подобного.)

Что происходит:

  1. Браузер переходит на localhost:3000/auth/steam
  2. Node перенаправляет браузер на steam openId
  3. Steam, при успешном входе в систему и предоставлении авторизации, перенаправляет обратно на http://localhost:3000/auth/steam/return

Что происходит дальше?

  • Ну, во-первых, сохраните данные этого профиля в стратегии Passport в профиль пользователя или, по крайней мере, в сеанс пользователя.
  • затем перенаправьте пользователя обратно в приложение Angular. Что-то вроде этого:

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

(Используйте здесь HashLocationStrategy, чтобы вы четко видели, куда я вас перенаправляю.)

  • Теперь ваш маршрут /authcallback в Angular, вероятно, должен еще раз напрямую попасть в конечную точку, чтобы получить данные аутентификации, прежде чем выполнять собственные перенаправления.

Альтернативы:

Теперь эту последнюю часть можно было бы сделать по-другому. Вы можете сделать что-то вроде перенаправления с узла обратно на индекс или на любой исходный маршрут (вы можете добавить их в качестве параметров и т. д.). Затем создайте службу Angular, которая всегда проверяет наличие данных аутентификации с серверной частью.

Или вы можете сделать так, чтобы серверная часть вашего узла встраивала информацию в index.html Angular или любую другую страницу, которую вы используете. Вы знаете, старая школа, серверная сторона вводит данные, возможно, в тег скрипта с чем-то вроде ejs или jade. Это было бы быстрее, но я бы все равно не доверял ему слепо на клиенте (или сервере) и перепроверил бы, может быть, в фоновом режиме.

person Zlatko    schedule 04.01.2018
comment
Мне тоже помог ответ. Хорошо написано, спасибо Златко. - person filipbarak; 21.02.2018

То, что вы делаете в своем коде, вызывает запрос GET на ваш собственный сервер. Я вообще не вижу перенаправления страниц.

Если вы хотите перенаправить пользователя на внешний веб-сайт, вам нужно отправить пользователя туда одним из следующих способов:

Из HTML-файла:

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

Из файла вашего компонента .ts:

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

Если вы хотите перенаправить пользователя на другую страницу вашего сайта, вам нужно использовать Angular Router:

Из HTML-файла:

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

Из файла вашего компонента .ts:

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

Итак, ваш компонент теперь становится:

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');
    });
  }

}

Дополнительные примеры можно найти с помощью простого поиска Google, например ниже https://coryrylan.com/blog/introduction-to-angular-routing

person klonq    schedule 29.12.2017
comment
Перенаправление выполняется с помощью метода Passport authenticate автоматически. - person Nikola Stojaković; 29.12.2017

Насколько я понимаю, вы никогда не направляете пользователя на страницу Steam. Ваш комментарий к клонгу: "Перенаправление осуществляется через Паспорт". Это может быть, однако вы никогда не отправляете пользователя на определенную страницу. Вы просто делаете запрос GET из своего интерфейса.

Об ошибке политики того же происхождения. Я предполагаю, что это вызвано Passport, потому что вы используете Cors на своем экспресс-сервере. Думаю, лучшим решением будет создание простого прокси. Если вы используете интерфейс командной строки, вы можете использовать этот пример.

person Robin Dijkhof    schedule 29.12.2017

Прежде всего, вы не отправляете свой запрос на вход в экспресс-бэкэнд. Вы должны отправить запрос на вход в Steam oidc авторизовать конечную точку. Посмотрите, что говорит Steam:

При использовании OpenID пользователь начинает в веб-браузере со стороннего веб-сайта. Когда пользователь хочет войти/связать свою учетную запись с этим веб-сайтом, используя OpenID, сайт направляет пользователя к форме входа на веб-сайте сообщества Steam. После того, как пользователь ввел свои учетные данные для входа в Steam, веб-браузер пользователя автоматически перенаправляется обратно на сторонний веб-сайт с добавлением некоторых дополнительных данных, специфичных для OpenID, к возвращаемому URL-адресу. Затем библиотека OpenID сайта может использовать эти данные для проверки и получения SteamID пользователя.

Он называется Oidc, и вам повезло, что есть две хорошие библиотеки для Angular. Это (рекомендуется) и Это.

Что нужно сделать вашему экспресс-серверу, так это проверить токен, полученный от вашего углового клиента, перед запросом. Я не очень хорошо знаком с экспрессом, но я уверен, что есть как минимум пара библиотек для проверки токена.

Также вам необходимо провести дополнительные исследования по этой теме.

person Okan Aslankan    schedule 01.01.2018