Вход в Okta с помощью angular через Node

Я создаю стратегию входа в систему для своего веб-приложения angular 6. Пользователь нажимает кнопку входа в систему, и он запускает HTTP-запрос к localhost: 3000/login на моем сервере node. Я использую okta в качестве аутентификатора и использую стратегию oidc с паспортом. Если я перехожу на localhost:3000/login, он выполняет перенаправление, как и ожидалось, на вход okta на портал. Когда я пробую это с моего углового интерфейса, я получаю ошибку CORS. Я включил Access-Control-Allow-Origin с подстановочным знаком.

//app.js

require("dotenv").config();
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const routes = require("./routes/routes");
const mongoose = require("mongoose");
const casperRoutes = require("./routes/casper-routes");
const oktaRoutes = require("./routes/okta-routes");
const slackRoutes = require("./routes/slack-routes");
const session = require("express-session");
const passport = require("passport");
const OidcStrategy = require("passport-openidconnect").Strategy;

const oktaBaseAuth = process.env.OKTA_AUTH_URI;
mongoose
  .connect(
    "mongodb+srv://xxxxx",
    { useNewUrlParser: true }
  )
  .then(() => {
    console.log("connected to database!");
  })
  .catch(() => {
    console.log("connection failed");
  });

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin, X-requested-With, Content-Type, Accept"
  );
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, PATCH, PUT, DELETE, OPTIONS, PUT"
  );

  next();
});

app.use(
  session({
    secret: "xxx",
    resave: false,
    saveUninitialized: true
  })
);
app.use(passport.initialize());
app.use(passport.session());
passport.use(
  "oidc",
  new OidcStrategy(
    {
      issuer: oktaBaseAuth + "/oauth2/default",
      authorizationURL: oktaBaseAuth + "/oauth2/default/v1/authorize",
      tokenURL: oktaBaseAuth + "/oauth2/default/v1/token",
      userInfoURL: oktaBaseAuth + "/oauth2/default/v1/userinfo",
      clientID: process.env.OKTA_AUTH_CLIENT_ID,
      clientSecret: process.env.OKTA_AUTH_CLIENT_SECRET,
      callbackURL: 'http://localhost:3000/authorization-code/callback',
      scope: "openid profile"
    },
    (issuer, sub, profile, accessToken, refreshToken, done) => {
      return done(null, profile);
    }
  )
);
passport.serializeUser((user,next)=>{
  next(null,user);
});
passport.deserializeUser((obj,next)=>{
  next(null,obj);
});


app.use('/login', passport.authenticate('oidc'));
app.use('/authorization-code/callback', 
passport.authenticate('oidc', {failureRedirect: '/error'}),

(req,res)=>{
  res.redirect('/');

});
function checkLogged(req,res,next){
  if (req.isAuthenticated()){
    return next();
  }
  res.redirect('/login');
}

app.use("/api/casper",checkLogged, casperRoutes);
app.use("/api/data",checkLogged, routes);
app.use("/api/okta", checkLogged,oktaRoutes);
app.use("/api/slack", checkLogged, slackRoutes);

module.exports = app;

Фронтальная служба

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Subject, Observable } from "rxjs";
import * as OktaSignIn from "@okta/okta-signin-widget";
import { Injectable } from "@angular/core";
import { Router } from "@angular/router";


@Injectable({
  providedIn: "root"
})
export class OktaService {
  widget;
  isAuthenticated = false;
  user;
  private headers = new HttpHeaders();

  private authStatusListener = new Subject<boolean>();

  constructor(private http: HttpClient, private router: Router) {}

  loginUser(){
    this.http.get('http://localhost:3000/login').subscribe(res=>console.log(res));
  }


}

И ошибка

Failed to load https://dev-795809.oktapreview.com/oauth2/default/v1/authorize?response_type=code&client_id=0oag898j7zj7j8jqw0h7&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthorization-code%2Fcallback&scope=openid%20openid%20profile&state=rtFMOtsHHBOc90UcM3nLIz%2Fp: Redirect from 'https://dev-795809.oktapreview.com/oauth2/default/v1/authorize?response_type=code&client_id=0oag898j7zj7j8jqw0h7&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauthorization-code%2Fcallback&scope=openid%20openid%20profile&state=rtFMOtsHHBOc90UcM3nLIz%2Fp' to 'https://dev-795809.oktapreview.com/login/login.htm?fromURI=/oauth2/v1/authorize/redirect?okta_key=c8hyLEuNV3KeYJyLfw2EU9xDjqsqeSOLft2jLzh-07E' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

Я также включил CORS в своем приложении OKTA. Я где-то читал, что это может быть связано с тем, что я не могу разрешить CORS с подстановочным знаком для данных авторизации. Как я могу подключиться к серверной части для входа в систему, используя внешний интерфейс angular, работающий на другом порту?


person Pari Baker    schedule 11.09.2018    source источник


Ответы (1)


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

  loginUser() {
    window.location.href = 'http://localhost:3000/login'
  }

Проблема с этим подходом заключается в том, что вы, скорее всего, будете перенаправлены обратно в приложение Node после успешного входа в систему, а не в приложение Angular. Вы можете написать собственный код в своем приложении Node для перенаправления обратно к рефереру после аутентификации. Я сделал это с помощью Spring Security, но не знаю, как это сделать для Node.

Другой вариант — использовать наш Angular SDK и выполнить аутентификацию в приложении Angular, а также настроить Node API в качестве сервера ресурсов, который просто проверяет переданный токен доступа.

person Matt Raible    schedule 11.09.2018
comment
Хорошо, спасибо, я попробую это. В идеале, если мой сервер аутентифицирует токен доступа, это нормально, но как мой сервер разрешит пользователю доступ к защищенным маршрутам. Например, скажем, пользователь А может войти в систему и делать определенные вещи, которые пользователь Б не может. Могу ли я отправить электронное письмо пользователя с токеном, чтобы подтвердить это? - person Pari Baker; 12.09.2018
comment
Вы можете добавить групповое утверждение в свой ID или маркеры доступа, а затем используйте их для определения разрешений. Вы также можете использовать электронную почту, но это может быть немного мелко. - person Matt Raible; 12.09.2018
comment
Хорошо, я пытался сделать это через angular, используя службу OktaAuth, отлично работает, но когда я добавляю свои routeGuards и активирует перенаправление, я снова получаю ошибку CORS. Я добавил оба URL-адреса в Okta, и локальный хост: 4200 также присутствует в качестве надежного источника. - person Pari Baker; 13.09.2018
comment
Перенаправление с 'dev-795809.oktapreview.com/oauth2/default/v1/' на 'dev-795809.oktapreview.com/login/login.htm?fromURI=/ oauth2/v1/» заблокирован политикой CORS: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Таким образом, Origin 'null' не имеет доступа. - person Pari Baker; 13.09.2018
comment
Я заметил, что это не охранники вызывают ошибку CORS, а когда я вместо этого добавляю свои службы. Таким образом, любые страницы с внедренными службами возвращают ошибку cors. - person Pari Baker; 13.09.2018