2020에 작성한 노트를 옮겨 적은 것입니다.
일반적인 경우는 구글, 페이스북과 같은 authorizer (혹은 provider)를 사용하는 것이지만, 여기서는 authorizer도 같이 구현하는 경우를 정리함.
const passport = require('passport')
, OAuth2Strategy = require('passport-oauth').OAuth2Strategy;
passport.use('provider', new OAuth2Strategy({
authorizationURL: 'https://www.provider.com/oauth2/authorize',
tokenURL: 'https://www.provider.com/oauth2/token',
clientID: '123-456-789',
clientSecret: 'shhh-its-a-secret'
callbackURL: 'https://www.example.com/auth/provider/callback'
},
function(accessToken, refreshToken, profile, done) {
User.findOrCreate(..., function(err, user) {
done(err, user);
});
}
));
위의 verify callback은 provider, 즉 authorizer가 발급한 토큰들을 적당히 처리함.
// Redirect the user to the OAuth 2.0 provider for authentication. When
// complete, the provider will redirect the user back to the application at
// /auth/provider/callback
app.get('/auth/provider', passport.authenticate('provider'));
// The OAuth 2.0 provider has redirected the user back to the application.
// Finish the authentication process by attempting to obtain an access
// token. If authorization was granted, the user will be logged in.
// Otherwise, authentication has failed.
app.get('/auth/provider/callback',
passport.authenticate('provider', { successRedirect: '/',
failureRedirect: '/login' }));
유저 접근 시, 처음에 provider로 리디렉트 해준 뒤, 유저의 권한이 인증되면 application entry로 접근하기 위한 callback url로 리디렉트 된다
유저의 ID, Secret을 가지고 grant와 token (access token, refresh token)을 발급하는 역할을 한다.
passport-oauth2 개발자가 만든 oauth2orize(https://yarnpkg.com/package/oauth2orize)를 사용하지만, 더 나은 방법이 있는지 알아봐야 함.
위 OAuth2Strategy에서 설정한 authorizationURL, tokenURL 엔드포인트를 구현한다.
app.get('/oauth2/authorize',
login .ensureLoggedIn(),
server.authorize(clientID, redirectURI, done) => {});
app.post('/oauth2/token',
passport.authenticate(['basic', 'other-strategy', ...]),
server.token(),
server.errorHandler(),
);
유저가 GET /authorize 요청
response_type
: 'code'REQUIRED. The value MUST be one of "code" for requesting an
authorization code as described by Section 4.1.1, "token" for
requesting an access token (implicit grant) as described by
Section 4.2.1, or a registered extension value as described by
Section 8.4.
client_id
: Public identifierredirect_uri
: Authorization 서버가 인증 승인 후 user 요청 리디렉트 할 주소scope
: space-separated strings. state
: 요청하는 단에서 보내는 random string. 인증 후 return 값이 해당 state와 같은지 체크해야함. 참고. Authorize의 엔드포인트에서 server.authorize() 실행
Obtaining the user's authorization involves multiple request/response pairs. During this time, an OAuth 2.0 transaction will be serialized to the session. Client serialization functions are registered to customize this process, which will typically be as simple as serializing the client ID, and finding the client by ID when deserializing.
server.serializeClient(function(client, done) {
return done(null, client.id);
});
server.deserializeClient(function(id, done) {
Clients.findOne(id, function(err, client) {
if (err) { return done(err); }
return done(null, client);
});
});