인증

2014-01-23 1 views
20

나는 많은 다른 대답 가능한 게시물을 읽으려고했지만, 나는 아직도 꽤 내 요구에 맞는 솔루션에 정착 할 수 없습니다. 나는, 로그인 등 사용자 인증을 처리하는 가장 좋은 (가장 효율적인,하지만 대부분 더 안전한) 방법을 해결하기 위해 노력하고있어인증

내가 가지고 Node.js를 서버, 고속에서 실행; Angular.js 웹 앱이 있습니다. iOS 앱이 있습니다. Express/Node.js로 RESTful API를 공개합니다.

쿠키

쿠키를 사용하고, 서버 측에서 세션 ID/로그인 토큰을 저장했다 읽기 첫 번째 일이 (해시)와 클라이언트 측 (해시되지 않은). 클라이언트는 각 요청에 대해이 id를 전송하고, 서버는이를 해시하고, 구문 분석하고 그에 따라 요청을 처리합니다. 이것은 RESTful (큰 문제는 아님)을 느끼지는 않지만 더 중요한 것은 사용자 이름/비밀번호 인증 (예 : 말풍선)과 쿠키 기반 인증 (예 : 웹 앱)을위한 API를 복제해야한다는 것입니다.

이 또 다른 문제 : 나는 한 사용자, 예를 들어, 여러 연결이 있다면 내가 어떻게 할 것인지 그들은 두 개의 브라우저 인 iPhone과 iPad에 로그인되어 있습니다. 세션 ID를 저장하는 것이 배열이 될 필요가 있습니까?

HTTP 기본 인증

은 다음 아이디어는 각 요청과 함께 사용자 이름과 암호를 전송해야하기 때문에 충분히 쉽게 보이지만하지 않는 것이 좋습니다 (SSL)와 HTTP 기본 인증을 사용하는 것이 었습니다. HTTP Basic Auth로 할 경우 'Remember Me'기능을 사용하기 위해 사용자 이름과 암호를 쿠키 (또는 HTML 로컬 저장소)에 저장하겠습니까? 또는 두 가지를 결합 할 수 있습니까? 실제 요청 (새 게시물 게시 등)에 HTTP 기본 인증을 사용하고 초기 로그에 대한 쿠키에 저장된 세션 ID를 순서대로 사용하거나 측면을 기억합니까?

는 사용자의 암호를 전송하는 것보다 더 안전한 세션 ID를 전송? 방법? 세션 ID는 표면 상으로는 암호로 동작하므로 저에게 암호를 전송하는 것과 동일한 보안 문제가 있습니다.

기본 인증은 모든 플랫폼에서 지원되는 것으로 보이는 것이 이상적입니다. 주요 단점은 각 요청마다 클라이언트 인증 데이터를 전송해야하는 것 같습니다. 이 문제를 완화 할 수있는 방법이 있습니까?

OAuth

OAuth는 내 요구에 과도한 것처럼 보입니다. 내 API를 테스트하기 위해 컬 명령을 수행 할 수있는 능력을 잃을 것이라고 생각합니다. OAuth는 쿠키 방법보다 어떻게 개선 되었습니까?

아마 당신은 말할 수

, 내가 사용할 수있는 다양한 정보에 의해 조금 혼란, 그래서 당신이 좋은 링크-적용이의 집합이있는 경우 시나리오를-I는 읽을 싶어요. 모든 플랫폼에 맞는 솔루션을 찾으려고 노력하고 있지만 가능한 한 안전합니다. 또한, 내 용어가 잘못되어 있다면, 나를 쉽게 찾을 수 있기 때문에 나를 교정하십시오.

감사합니다.

업데이트 :

나는이 문제에 대해 생각해 봤는데, 내가 생각을 했어. 이것이 좋은지 확신 할 수 없기 때문에 이것이 벙어리/불안전 한/피드백인지 알려주세요. 사용자가 로그인 할 때

, 우리는 임의의 세션 ID (소금 등)을 생성합니다.이 선택 사항 인 세션 ID가 클라이언트에게 전송되며 클라이언트는 쿠키를 저장할 수 있습니다 (예 : 쿠키). 세션 ID는 데이터베이스에 저장됩니다.

이 세션 ID는 HTTP 인증 헤더 또는 검색어 문자열으로 각 요청과 함께 선택적으로 전송되거나 클라이언트가 원하는 경우 사용자 이름과 비밀번호를 보낼 수 있습니다 (이는 정규 REST API를 제공함). 서버 측에서는 먼저 세션 id 매개 변수를 확인하고,없는 경우 username/password를 확인합니다. 어느 쪽에도 오류가 없다면.

서버에서 세션 ID가 올바른 사용자 이름과 연결되어 있는지 확인합니다. 존재한다면 요청을 완료합니다.

사용자가 로그인 할 때마다 새 세션 id를 만들거나 현재 세션 ID를 삭제하고 요청시 요청에 대한 응답과 함께 전송합니다.

기본 인증을 사용하여 정규 REST API를 사용하고 세션을 유지 관리하거나 기능을 기억할 수 있다고 생각합니다. 그것은 여러 로그인 문제를 해결하지 않지만, 그렇지 않으면 나는이 방법을해야한다고 생각합니다. 저에게 알려주세요.

+3

passport.js를 보셨습니까? http://passportjs.org/ –

+1

@MWay 그 점에 대해 감사드립니다. 나는 그것을 더 깊이 조사 할 것이다. '업데이트'섹션에 게시 한 솔루션의 보안에 대해 말씀해 주시겠습니까? 실용적이지 않다면 아마도 여권과 함께 갈 것이라고 생각합니다. – matthewpalmer

+0

@matt,이 session_ids 영원을 만들 필요가 없습니다 ... 캐시에만 DB에 저장하지 마십시오 ... 우리는이 토큰을 24 시간 ttl로 redis에 저장하고 각 사용자 쿼리에서이 ttl을 갱신합니다. .. 사용자가 24 시간 침묵했다면이 토큰이 만료되었습니다 ... –

답변

25

각 요청마다 토큰을 (자동으로) 보낼 수있는 토큰 기반 인증을 사용합니다. 한 번 로그인하면 서버가 토큰을 제공하여 각 요청과 함께 보낼 수 있습니다. 이 토큰은 HTML 헤더에 추가되므로 브라우저에 대한 각 요청을 수정할 필요가 없습니다.

API에서 특정 호출을 설정하여 항상 토큰이 필요하지만 다른 것들은 토큰으로 보호되지 않을 수 있습니다.

익스프레스를 들어, 당신이 사용할 수있는 표현 - JWT

var expressJwt = require('express-jwt'); 

// Protect the /api routes with JWT 
app.use('/api', expressJwt({secret: secret})); 

app.use(express.json()); 
app.use(express.urlencoded()); 

당신이 당신의 특급 서버에서이 기능을 만들 수 있습니다 인증하려는 경우 (https://www.npmjs.org/package/express-jwt)

:

app.post('/authenticate', function (req, res) { 
    //if is invalid, return 401 
    if (!(req.body.username === 'john.doe' && req.body.password === 'foobar')) { 
    res.send(401, 'Wrong user or password'); 
    return; 
    } 

    var profile = { 
    first_name: 'John', 
    last_name: 'Doe', 
    email: '[email protected]', 
    id: 123 
    }; 

    // We are sending the profile inside the token 
    var token = jwt.sign(profile, secret, { expiresInMinutes: 60*5 }); 

    res.json({ token: token }); 
}); 

보호 통화 뭔가/api로 시작하는 :

app.get('/api/restricted', function (req, res) { 
    console.log('user ' + req.user.email + ' is calling /api/restricted'); 
    res.json({ 
    name: 'foo' 
    }); 
}); 

각도 적용 N 당신이 로그인 할 수 있습니다 :

$http 
     .post('/authenticate', $scope.user) 
     .success(function (data, status, headers, config) { 
     $window.sessionStorage.token = data.token; 
     $scope.message = 'Welcome'; 
     }) 
     .error(function (data, status, headers, config) { 
     // Erase the token if the user fails to log in 
     delete $window.sessionStorage.token; 

     // Handle login errors here 
     $scope.message = 'Error: Invalid user or password'; 
     }); 

그리고 인증 인터셉터를 작성하여, 자동으로 모든 요청 토큰을 보내드립니다 :

myApp.factory('authInterceptor', function ($rootScope, $q, $window) { 
    return { 
    request: function (config) { 
     config.headers = config.headers || {}; 
     if ($window.sessionStorage.token) { 
     config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token; 
     } 
     return config; 
    }, 
    response: function (response) { 
     if (response.status === 401) { 
     // handle the case where the user is not authenticated 
     } 
     return response || $q.when(response); 
    } 
    }; 
}); 

myApp.config(function ($httpProvider) { 
    $httpProvider.interceptors.push('authInterceptor'); 
}); 

를 로컬 스토리지를 지원하지 않는 오래된 브라우저를 지원해야하는 경우 . $window.sessionStorage을 AmplifyJS (http://amplifyjs.com/)와 같은 라이브러리로 교체 할 수 있습니다. Amplify는 사용 가능한 localstorage가 무엇이든 사용합니다. 이것은 이런 식으로 번역하는 것 :

if (data.status === 'OK') { 
     //Save the data using Amplify.js 
     localStorage.save('sessionToken', data.token); 
     //This doesn't work on the file protocol or on some older browsers 
     //$window.sessionStorage.token = data.token; 
     $location.path('/pep'); 
    } 
    }).error(function (error) { 
    // Erase the token if the user fails to log in 
    localStorage.save('sessionToken', null); 
    // Handle login errors here 
    $scope.message = 'Error: Invalid user or password'; 
    }); 

그리고 우리가 교환 authintercepter :

http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/

+0

하지만 이걸로 나는 매번 사용자 이름과 암호를 보내야하며 XSS 공격이 가능할 수 있습니다. 대신 왜 쿠키를 사용하지 않습니까? 적어도 비밀번호는 평범하지 않습니다. – nick

+3

아니요. HTTP POST를 통해 한 번만 사용자 이름과 비밀번호를 보내면됩니다. 이것은 쿠키를 사용하는 로그인과 다르지 않습니다. 그런 다음 HTTP 헤더의 토큰을 사용하여 HTTP 헤더에 설정된 쿠키를 사용하는 대신 자신을 인증합니다. XSS로부터 자신을 보호하려면 어쨌든 응용 프로그램이받는 모든 입력을 필터링해야합니다. 그리고 전선을 통해 데이터에 HTTPS를 사용하는 것이 타당합니다. 토큰 기반 인증의 장점은 내 대답에 링크 된 게시물에 설명되어 있습니다. –

1

이 유무 :

angular.module('myApp.authInterceptor', ['myApp.localStorage']).factory('authInterceptor', [ 
    '$rootScope', 
    '$q', 
    'localStorage', 
    function ($rootScope, $q, localStorage) { 
    return { 
     request: function (config) { 
     config.headers = config.headers || {}; 
     config.headers.Authorization = 'Bearer ' + localStorage.retrieve('sessionToken'); 
     return config; 
     }, 
     response: function (response) { 
     if (response.status === 401) { 
     } 
     return response || $q.when(response); 
     } 
    }; 
    } 
]); 

이 문서에서 AmplifyJS를 제외하고 모든 것을 찾을 수 있습니다 yeoman 발전기를 각도와 노드로 보십니까?발전기 앵귤러 풀 스택은 여권을 사용하는 사용자 인증을위한 매우 훌륭한 구조를 가지고 있습니다.

당신은 여기에서 예를 볼 수 있습니다

코드 : https://github.com/DaftMonk/fullstack-demo

결과 : http://fullstack-demo.herokuapp.com/

는 희망이 도움이!

0

나는 generator-angular-fullstack을 사용하며/api 서비스는 보안되지 않으며/api/users/me, logout에서 _id를 가져 와서/api/users/your_id_here로 이동하면/API가 확보되지 않았습니다.