Okta通过Node使用angular登录

时间:2018-09-11 19:51:52

标签: node.js angular okta

我正在为我的angular 6 Web应用程序创建登录策略。用户单击登录按钮,它会触发对我的节点服务器上的localhost:3000 / login的HTTP请求。我正在使用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.

我也在我的OKTA应用程序上启用了CORS。我在某处读到这可能是因为我无法使用通配符来解析授权数据的CORS。如何使用在不同端口上运行的有角度前端连接到后端进行登录?

1 个答案:

答案 0 :(得分:0)

发生这种情况是因为您试图向后端发出XHR请求。如果您将其更改为重定向到后端,则应该可以使用。

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

此方法的问题在于,成功登录后,很可能会将您重定向回Node应用程序,而不是Angular应用程序。您可以在Node应用程序中编写自定义代码,以在身份验证后重定向回引荐来源网址。我已经使用Spring Security做到了这一点,但是我不确定如何在Node上做到这一点。

另一种选择是使用我们的Angular SDK并在Angular应用中进行身份验证,然后将Node API设置为资源服务器,以简单地验证传入的访问令牌。