PassportJS의 OAuth flow 엔진 뚜껑에서 훔쳐보기

도서관이 아주 좋아요.그것들은 표준화, 광범위한 호환, 깨끗한 방식으로 흔히 볼 수 있는 임무를 완성하고, 우리가 일반적으로 무관심한 세부 사항을 추상화한다.그것들은 우리가 신분 검증, 데이터베이스 처리, 폼 검증의 세부 사항을 걱정하지 않고, 우리가 생각하는 것을 위해 코드를 작성하기만 하면 된다는 것을 돕는다.
그러나 만약 어떤 일이 예상대로 되지 않는다면 어떤 일이 일어날까요?만약 네가 단지 블랙박스의 버튼을 눌렀을 뿐이라면, 너는 무슨 문제가 생겼는지 어떻게 알았니?
조만간 우리가 빌려온 도서관이 어떻게 이런 사소한 일을 하는지 이해할 필요가 있을 것이다🎶 우리가 어디에서 모퉁이를 잘못 돌았는지 찾아내면 바로잡을 수 있다.
내가 개인 프로젝트를 위해 PassportJS을 배우기로 결정했을 때 나는 이랬다.본고에서 저는 PassportJS를 사용하여 OAuth 흐름을 처리할 때 가장 파악하기 어려운 부분을 깊이 있게 연구하고자 합니다.
만약 평소와 같이 OAuth를 위해PassportJS를 어떻게 실현하는지에 대한 완전한 강좌가 필요하다면, 저는 당신에게 건의합니다.아니면 OAuth를 어떻게 추는지 복습만 하고 싶다면 이 주제를 방문해 보세요.

인덱스

  • 기본 여권 설정
  • 콜 인증
  • 번 ~ verify
  • WTF는 서열화 및 반서열화된
  • 전체 로그인 프로세스
  • 검증된 요청 흐름
  • 기본 PassportJS 설정


    우리는 다음 몇 가지부터 시작할 수 있습니다. 올바르게 설정된passport 정책과 두 개의 노드 (하나는 권한을 부여하는 데 사용되고, 다른 하나는 방향을 바꾸는 데 사용됩니다.)

    호출 확인


    Passport의 가장 좋은 점은 임의의 정책을 등록하고 호출 중인 루트에 따라 authenticate 방법으로 어떤 정책을 사용하는지 알려줄 수 있다는 것입니다. 예를 들어


    passport.authenticate('github');
    

    이 정책 중 하나를 설정할 때, 매개 변수와 검증 리셋 함수를 정의해야 합니다. 이 함수는 프로그램에서 되돌아오는 사용자 데이터를 처리합니다


    적어도 나에게 이상한 것은 두 개의 다른 노선에서 passport.authenticate()으로 전화를 걸었던 이유


    하지만 비결은:


    authenticate()을 처음 호출할 때passport는 이전에 등록된 함수에 전달된 문자열 이름을 통해 정책이 있는지 확인하려고 시도합니다.만약 그렇다면, 공급자의 권한 수여 단점을 클릭하여 OAuth 춤을 시작합니다.만약 찾을 수 없다면, 전략이 알 수 없다는 오류 하나만 던집니다.p>

    현재 두 번째 호출은 공급자의 OAuth 서버에서 리셋 중입니다. 루트로 리셋 중입니다.이번에는 완전히 똑같아 보이지만, 패스포트는 OAuth 흐름의 두 번째 단계를 감지하고, OAuth 영패를 요청하기 위해 방금 얻은 임시 코드를 사용하는 정책을 알려 줍니다.그 전략은 어떻게, 어디서 요구를 하는지 정확히 알고 있다.


    이후에 무슨 일이 일어날지


    세계로 가는 길


    PassportJS의 OAuth 흐름에 대한 나의 최신 손그림 작품을 보십시오.이때 우리는 getProfile():



    예전보다 더 곤혹스러우면 계속 읽으세요.나는 반드시 좋아질 것이다


    OAuth 영패를 받은 후 가장 먼저 발생한 일은 이 정책이 사용자의 프로필을 가져오는 것입니다.이것은 정책의 내부 메커니즘으로 어느 특정한 공급자에게 그것을 요청하는지 알고 있습니다



    이어서 이 전략은 개요 파일을 내부에서 이 공급자가 정의한 모델로 해석한 다음에 그가 가지고 있는 모든 다른 데이터(accessToken,refreshToken과 개요 파일)와 함께 우리의verify 리셋에 전달하려고 시도한다


    정책을 설정할 때 인증 리셋을 정의한 것을 기억하십니까?현재 우리의 사용자 정의 코드가 처음으로 이 정책에 의해 실행되었다.이 예에서 우리는 이 사용자의 데이터베이스를 검사하고 필요할 때 기록을 작성하며 필요한 기타 내용을 검증할 수 있다


    필요한 모든 매개 변수를 검사한 후, 우리는done(또는verify callback의 리셋 함수)를 호출할 것입니다. 이것은 그의 네 번째이자 마지막 함수 매개 변수입니다.우리는 null(오류 없음)과 우리가 생각하는 모든 정보를 사용자에게 전달합니다


    (accessToken, refreshToken, profile, done) => {
      // verify things here and then...
      done(null, {accessToken, profile})
    }
    

    마지막으로, Passport은 자신의 req.login()을 실행합니다. 이것은 사용자를 req.user에 저장하여 더욱 사용하도록 합니다



    위의 도표를 다시 보면 이제 더 잘 이해할 수 있을 거예요


    다음은 serializeUser👇


    WTF는 서열화되고 반서열화되었다


    Serialization is the process of translating data structures or object state into a format that can be stored or transmitted and reconstructed later.
    ––Wikipedia's Serialization Article


    우리의 예에서'데이터'는 우리가 줄곧 낭비하고 있는 그 사용자를 가리킨다.Passport의 serializeUser 방법에서 우리의 사용자 정의 코드는 세션에서 어떤 정보를 보존해야 하는지 정의해야 합니다. 나중에 Serialize User에 전달된 done 메타데이터를 통해 전체 사용자를 검색할 수 있습니다.


    이것은 패스포트의 서열화된 사용자 방법으로 형식이 매우 간단합니다:




    passport.serializeUser((user, done) => done(null, {
      id: user.profile.id,
      accessToken: user.access_token
    }))
    

    ☝️이 대상은 req.userreq.session.passport.user에서 종료되어 후속 요청에 사용할 수 있습니다


    현재 deserializeUser에 대해 이 함수는 세션에 존재하는 사용자 데이터를 수신하고 데이터베이스에서 사용자의 모든 데이터를 가져옵니다.예:


    passport.deserialize((user, done) => {
      dbHelper.getUser(user.id)
        .then(profile => done(profile))
    })
    

    done에 전달되는 모든 정보는 req.user에서 제공됩니다.


    전체 로그인 프로세스


    이전 그림을 확대해 봅시다. 특히 OAuth 무용이 끝난 후에요.나는 그것을 더욱 깊이 연구하고 싶다. 왜냐하면 내가 OAuth를 위해PassportJS를 사용하기 시작했을 때, 그것은 매우 신비로웠던 것을 기억하기 때문이다.p>


    이것이 바로 사용자가 "네, 허락합니다"라고 말한 것입니다. 저희 프로그램이 그들의 방문 영패를 받은 후 발생한 상황:


    • Passport OAuth 토큰을 공급업체로부터
    • 수신
    • 사용자의 프로필 정보를 얻기 위해 사용합니다
    • 에서 verifyCallback을 실행하고 완성되면 사용자 대상을 자신에게 전달하는 done에서
    • 으로 리콜
    • Passport는 자신의 방법인 req.login()을 사용하고 그 방법인 serializeUser()을 사용합니다.
      serializeUser는 세션에 저장할 사용자 정보를 추출한 다음 경로를 바꾸는 다음 처리 프로그램을 계속 사용합니다.

    인증된 요청 흐름


    지금은 이 모든 것이 다 좋은데, 우리 프로그램은 사용자가 더 많은 요청을 할 때 인증을 거치고, 개인 정보를 안전하게 제공할 수 있다는 것을 어떻게 알았습니까?


    이것은 완전한 강좌가 아니지만, 계속 공부하고 있다면 서버 코드에 비슷한 내용이 있을 수 있습니다:


    server.use(passport.initialize())
    server.use(passport.session())
    

    이 줄들은 두 개의 중간부품을 설정하여 서버에서 받은 모든 요청에서 실행합니다


    인증된 요청을 보낼 때 Express는 세션을req에 불러와서 우리의 서열화된 사용자 데이터를 req.session.passport.user에서 사용할 수 있도록 합니다


    그리고 첫 번째 중간부품 initialize()은 요청에서 이 사용자를 찾으려고 시도합니다. 이 사용자가 존재하지 않으면 빈 대상으로 만듭니다. (이것은 이 사용자가 인증을 거치지 않았다는 것을 의미합니다.)


    그리고 session()은 서열화된 대상을 찾아서 요청이 인증되었는지 확인합니다



    이를 찾으면 deserializeUser에 전달하고 후자는 이를 사용하여 전체 사용자 데이터(데이터베이스에서 나올 수 있음)를 얻고 req.user에 추가하여 다른 요청을 만들 수 있습니다


    따라서 로그인할 때만 serializeUser을 호출하지만 deserializeUser은 전역 중간부품으로 모든 요청에 실행되며 완전한 사용자 대상이 인증된 요청에 사용할 수 있도록 합니다




    저는 OAuth 흐름에 대한 깊은 연구를 여기까지 마쳤습니다. 이것은 PassportJS의 비하인드 상황을 이해하는 데 도움이 되었으면 합니다.이 글을 쓰는 것은 틀림없이 나를 도와 약간의 의심을 없앴을 것이다.읽어주셔서 감사합니다


    내가 이 글을 연구할 때, 나는 우연히 J. Walton's의 이 멋진 unofficial documentation for PassportJS을 발견했다. 이것은 틀림없이 네가 다른 어떤 의문도 해결하는 데 도움을 줄 것이다

    좋은 웹페이지 즐겨찾기