61일차 (03-08-2021)

조상래·2021년 3월 8일
0

코드스테이츠

목록 보기
59/73

Authentication 스프린트 마지막 날이다. 오늘은 OAuth2.0 기반으로 소셜 로그인을 구현하는 과제이다. 인터넷을 하다보면 자주보는 것들 카카오톡으로 로그인하기, 네이버로 로그인하기 등등 이런것들이 OAuth 기반으로 이루어져있다.

먼저 OAuth2.0에 대해서 설명을 하자면,

1. 기본개념

OAuth2.0란 인증을 위한 표준 프로토콜의 한 종류로, 다른 사이트의 서비스를 제한적으로 사용할 수 있게 권한을 요청하는 프로세스를 단순화하는 프로토콜이다.

2. 흐름도

먼저 알아야할 개념들은

  • Resource Owner: 사용자로 보호된 자원에 접근하는 권한(Authorization Grant)을 제공.
  • Client: 클라이언트로 Resource Owner를 대신해 접근을 요청.
  • Authorization Server: Client가 부여 받은 Authorization Grant를 통해 Access Token부여.
  • Resource Server: Access Token을 이용한 요청을 받았을 때 적절한 응답을 반환.

1) Client는 Resource Owner에게 또는 Resource Server를 통해 간접적으로 권한 요청을 한다.

2) Resource Owner가 권한을 허락하면서 Client에게 Authorization Grant를 발급 해준다.

3) Authorization Server에 Client는 발급 받은 Authorization Grant를 보내어 유효성 검증을 한다.

4) Authorization Srver는 유효하다면 Access Token을 보내준다.

5) 받은 Access Token을 이용하여 Resource Server에 resource를 요청한다.

6) Access Token이 유효하다면 Resource Server는 요청을 처리해 적절한 응답을 반환 해준다.

(참고: http://blog.weirdx.io/post/39955)

아주 간략하게 썼지만, 기본적인 흐름은 대충 이해가 될 것같다. 그리고 핵심은 똑같이 토큰을 이용한 인증 방식이지만, 발급을 받는 과정이 다르다. 핵심 정보들은 모두 다른 곳에서 관리가 되어지고 client는 그저 요청만 반복하여 권한을 얻을 뿐이다. 특히 토큰 관리가 서버에서 이루어지며 그만큼 보안에도 좋다.

3. Github OAuth를 이용한 소셜 로그인 구현

오늘의 스프린트를 이용해 설명을 해보겠다. 참고로 각사이트 마다 OAuth를 이용하는 방법에는 차이가 있다. Github 기준에서 하는 설명이니 참고하길 바란다.

0) Github OAuth에 App등록

Client ID와 Client Secrets을 이용해 OAuth에 접근 할 것이다. Client Secrets의 코드는 생성시 전체 코드를 볼 수 있으며, 벗어나면 그 뒤론 볼 수가 없다. 그리고 다른 사람에게도 공개 되어선 안된다.
(참고: https://www.oauth.com/oauth2-servers/accessing-data/create-an-application/)

1) Authorization grant

// 클라이언트 코드
// 생략
class Login extends Component {
  constructor(props) {
    super(props)

    this.socialLoginHandler = this.socialLoginHandler.bind(this)
    this.GITHUB_LOGIN_URL = 'https://github.com/login/oauth/authorize?client_id={clientCode}&redirect_uri=http://localhost:3000'
  }

  socialLoginHandler() {
    window.location.assign(this.GITHUB_LOGIN_URL)
  }

// 생략

먼저 버튼을 누르면 Github OAuth를 통한 권한 요청을 받을 수 있는 코드를 작성하였다.

'https://github.com/login/oauth/authorize?client_id={clientCode}&redirect_uri=http://localhost:3000'

위와 같은 형태로 요청할 수 있으며 Resource Owner(나)가 권한요청에 수락한다면 Authorization Grant와 함께 명시된 URL로 redirect(이 부분은 OAuth에 App을 등록할 때 작성하였기 때문에 생략 가능) 되어진다.

위 결과,

Authorization Code가 같이 리디렉션이 된걸 볼 수 있다. 참고로 Authorization Code는 Authorization Grant의 여러가지 종류 중 하나이다.

2) AccessToken
위에서 받은 Authorization Code를 Authorization Server로 보내고 Server는 이를 이용해 AccessToken을 발급 받는다.

// 서버코드
// 생략
module.exports = (req, res) => {
  const params = {
    client_id: clientID, 
    client_secret: clientSecret, 
    code: req.body.authorizationCode,
  };
  
  axios.post('https://github.com/login/oauth/access_token', 
  params,
  {headers: {accept: 'application/json'}})
  .then(data => {
    const accessToken = data.data.access_token;
    res.status(200).send({accessToken: accessToken});
  }).catch(e => {console.log(e)})
}
// 생략

먼저 OAuth 앱 등록시 발급 받은 Client Id, Client Secert 그리고 클라이언트로 부터 받은 authorization code를 이용해 요청을 한다.

요청이 성공적으로 이루어지면 token을 받아 볼 수 있을 것이고 받은 토큰은 클라이언트로 전송해준다.

3) Resource request
클라이언트는 받은 토큰으로 Resource Server에 resource를 요청한다.

//클라이언트 코드
//생략
  async getGitHubUserInfo() {
    if (!this.props.accessToken) {
      return;
    } else {
      await axios.get('https://api.github.com/user', { 
        headers: { 
          authorization: `token ${this.props.accessToken}`, 
          accept: 'application/json' 
        }})
      .then(res => {
        const {name, login, html_url, public_repos} = res.data;
        this.setState({
          name,
          login,
          html_url,
          public_repos
        })
      })
    }
  }

  async getImages() {
    await axios('http://localhost:8080/images', {headers: { authorization: `token ${this.props.accessToken}` }})
    .then(data => {
      this.setState({images: data.data.images})
    })
  }
//생략

AccessToken을 이용한 요청으로 resource를 받아올 수 있다.

내일은 프로젝트 전 마지막 HA가 있는 날이다. 뭔가 조금 긴장이 된다. 잘 달려왔다 생각했지만 아직도 부족한게 많은 것 같기도 하다.

profile
Codestates Full IM26기 수료

0개의 댓글