Skip to content

4주차기술공유

sang-eun edited this page Nov 28, 2019 · 1 revision

기술 공유

예상시나리오

- 유저 로그인
- 개인 프로필 입력
- 메인페이지로 접속
- 피드작성
- 이미지 업로드
- 무한스크롤링

공유주제

oAuth 2.0

  • userclient server의 서비스 이용신청
  • client server에서 user에게 clientIDRedirectURI를 넘겨줌
  • userauthorization server에게 로그인 페이지를 요청
  • authorization server에서 user에게 로그인 페이지를 넘겨줌
  • userID/PASSWORD를 통해 로그인
  • authorization server에서 user에게 Authorization Code를 발급
  • userRedirectURIAuthorization Code를 전달
  • client server에서 authorization server에게 Authorization CodeAccess Token을 요청
  • authorization server에서 client server에게 Access Token 발급
  • client serveruser에 로그인 허가 및 서비스 이용
  • client server에서 resource serveruser정보 요구
  • resource server에서 client serveruser정보 허가

인증방식

Authorization Code Grant Type

  • client server에서 authorization code를 통해 access token을 발급받는 방식

Implicit Grant Type

  • access token을 바로 발급받는 방식

Resource Owner Password Credentials Grant Type

  • user의 정보를 받아서 client server에서 access code를 발급받는 방식

Client Credentials Grant Type : 클라이언트 자격 증명 타입

  • userresource server에 직접 요청하는 방식

reference reference

cors

CORS란 Cross Origin Resource Sharing의 줄임말로, Cross-Site Http Request를 가능하게하는 표준 규약입니다. 다른 도메인으로부터 리소스가 필요할 경우 cross-site http request가 필요합니다. 기존에는XMLHttpRequest는 보안상의 이유로 자신과 동일한 도메인으로만 HTTP요청을 보내도록 제한하였습니다. 즉 cross-origin http 요청을 제한하였죠 하지만 지속적으로 웹 애플리케이션을 개선하고 쉽게 개발하기 위해서는 이러한 request가 꼭 필요했습니다. 그래서 XMLHttpRequest가 cross-domain을 요청할 수 있도록하는 방법이 필요하게 되었죠. 이러한 요청을 바탕으로 CORS가 탄생하였습니다.

credentials 설정

서버에서 jwt토큰을 생성하고, 그걸 쿠키에 담아 전달하려 하였지만, 서버에서 보낸 쿠키가 전달되지 않는 문제에 봉착하였습니다.
이하와 같이 Apollo-client의 credentials 설정을 'include'로 바꾸는 것으로 문제를 해결하였지만,

const uploadLink = createUploadLink({
  uri: 'http://localhost:4000/graphql',
  credentials: 'include'
});

이유를 정확히 이해하지 못해서 찾아보게 되었습니다.
MDN의 Request.credentials 함수 설명에 따르면, credentials 설정에 따라 쿠키와 같은 정보를 주고 받을지 결정한다고 합니다.

Request 인터페이스의 credentials 읽기 전용 속성은 cross-origin 요청의 경우, 
user agent가 다른 도메인으로부터 cookie 들을 전달해야만 하는가 아닌가를 나타낸다. 
이것은 XHR 의 withCredentials flag 과 비슷하지만, (2개가 아니라) 3가지 값이 사용 가능하다 :

- omit: 절대로 cookie 들을 전송하거나 받지 않는다.
- same-origin: URL이 호출 script 와 동일 출처(same origin)에 있다면, 
user credentials (cookies, basic http auth 등..)을 전송한다. 이것은 default 값이다.
- include: cross-origin 호출이라 할지라도 언제나 user credentials 
(cookies, basic http auth 등..)을 전송한다.

따라서 포트가 다른 도메인에게 보내는 요청도 cross-domain이므로, include 설정을 해 주어야 했던 것입니다.

Access-Control-Allow-Origin 설정

하지만 include 설정을 하니 다음에는 Access-Control-Allow-Orign 에러가 발생하였습니다.

credentials가 include일 경우, Access-Control-Allow-Orign이 *이면 안된다는 것입니다. 즉, 반드시 허용하는 특정 주소를 지정해 줘야 한다는 것이지요. 이 설정을 하기 위해서는 서버에서 cors 모듈을 사용해 origin을 설정해 주어야 했습니다.

this.app.express.use(
      cors({ credentials: true, origin: config.clientHost })
    );

하지만 만약에 graphql과 같은 서버를 사용한다면, graphql 서버에서 응답 헤더의 Access-Control-Allow-Origin 부분을 *으로 다시 overwrite하게 됩니다. 따라서 graphql 서버에서도 cors 설정이 필요합니다.

const corsOptions = {
  origin: config.clientHost,
  credentials: true
};

const appOptions: Options = {
  port: PORT,
  endpoint: ENDPOINT,
  playground: PLAYGROUND,
  cors: corsOptions
};

이렇게 origin주소를 클라이언트로 설정을 해두니 문제없이 작동하는 것을 볼 수 있었습니다.

결론

결과적으로 cors 작업을 하면서

  • credential 요청인 경우에는(쿠키 등을 저장해서 다른 도메인과 주고받는 요청) 클라이언트에서 credentials: include 설정을 해 주어야 한다.
  • include로 수정한 다음에는 Access-Control-Allow-Origin헤더가 디폴트인 *(wild card)이면 응답을 제대로 전달하지 못하므로, origin 설정을 특정 주소로 해 주어야 한다. graphql의 경우 헤더가 overwrite 될 수 있으니 그 부분도 주의하자.

는 것을 배웠습니다.

Clone this wiki locally