Daily Front_Minhhk

OAuth,, sprint-auth-OAuth 참조 본문

Code개발일지

OAuth,, sprint-auth-OAuth 참조

Minhhk 2023. 1. 10. 00:56

OAuth

직접 작성한 서버에서 인증을 처리해 주는 것과는 달리, OAuth는 인증을 중개해 주는 매커니즘 이다.

 

OAuth 2.0은 인증을 위한 표준 프로토콜의 한 종류로

보안된 리소스에 엑세스하기 위해 클라이언트에게 권한을 제공하는 프로세스를 단순화하는 프로토콜 중 한 방법이다.

 

 

 

OAuth  용어

  • Resource Owner: 사용자이며 정보 제공자이기도 하기 때문에 Resource Owner라고 합니다.
  • Client: Resource Owner를 대신하여 보호된 리소스에 액세스하는 애플리케이션입니다.
  • Local Server: Client의 요청을 수락하고 응답할 수 있는 서버입니다.
  • Resource Server: 사용자의 정보를 저장하고 있는 서버입니다.
  • Authorization Server: 인증을 담당하고 있는 서버입니다. Access Token을 발급하는 인증 서버입니다.
  • Authorization Grant: Client가 Access Token을 얻는 방법을 의미합니다. 다음과 같은 방법들이 주로 사용됩니다.
    • Authorization Code Grant Type
    • Refresh Token Grant Type
  • Authorization Code: Authorization Grant의 한 타입으로 Access Token을 발급받기 위한 Code를 의미합니다.
  • Access Token: 보호된 리소스에 액세스하는 데 사용되는 인증 토큰입니다. 이 Access Token으로 이제 Resource Server에 접근할 수 있습니다.
  • Refresh Token: 발급받은 Access Token이 만료될 시 Refresh Token을 통해 새로운 Access Token을 받급받을 수 있습니다.

 

 

OAuth 인증 흐름

Authorization Code Grant Type

Authorization Code를 받아 Authorization Code를 통해 Access Token을 받는 방식을 말합니다.
이 유형은 Access Token이 사용자나 브라우저에 표시되지 않는다는 것을 의미하므로 Access Token이 다른 사람에게 누출될 위험이 줄어듭니다.

 

 

 

Refresh Token Grant Type

Authorization Code Grant Type으로 Access Token을 발급받은 후 Access Token이 만료된 경우 Refresh Token을 활용해 새로운 Access Token으로 교환하는 데 사용됩니다.

이를 통해 사용자와의 추가 상호 작용 없이 계속 유효한 액세스 토큰을 가질 수 있습니다.

 

 

 

 

 

 


🔥 서버는 구현이 되어 있고, 이번 스프린트에서는 client 만 수정 하면 된다!

 

client/App.js

getAccessToken과 Route의 <Mypage> 에 props 를 전달해준다

function App() {
  const [isLogin, setIsLogin] = useState(false);
  const [accessToken, setAccessToken] = useState("");

	const getAccessToken = async (authorizationCode) => {
    // 받아온 Authorization Code로 다시 OAuth App에 요청해서 Access Token을 받을 수 있습니다.
    // Access Token은 보안 유지가 필요하기 때문에 클라이언트에서 직접 OAuth App에 요청을 하는 방법은 보안에 취약할 수 있습니다.
    // Authorization Code를 서버로 보내주고 서버에서 Access Token 요청을 하는 것이 적절합니다.
    // TODO: 서버의 /callback 엔드포인트로 Authorization Code를 보내주고 Access Token을 받아옵니다.
    // Access Token을 받아온 후 state에 Access Token을 저장하세요
    await axios
      .post("<https://localhost:4000/callback>", {authorizationCode})
      .then((res) =>{
        console.log(res.data)
        setIsLogin(true) //액세스 토큰을 받아와 로그인 상태 true로 변경
        setAccessToken(res.data.accessToken) //Access Token 저장
      })
      .catch((err) => console.log(err));
  };

	useEffect(() => {
    // Authorization Server로부터 클라이언트로 리디렉션된 경우, Authorization Code가 함께 전달됩니다.
    // ex) <http://localhost:3000/mypage?code=5e52fb85d6a1ed46a51f>
    const url = new URL(window.location.href);
    const authorizationCode = url.searchParams.get("code");
    if (authorizationCode) {
      getAccessToken(authorizationCode);
    }
  }, []);

  return (
    <BrowserRouter>
      <div className="main">
        <div className="container">
          <Routes>
            <Route
              path="/"
              element={
                isLogin ? (
                  <Mypage accessToken={accessToken} setIsLogin={setIsLogin} setAccessToken={setAccessToken}/>
                ) : (
                  <Login />
                )
              }
            />
          </Routes>
        </div>
      </div>
    </BrowserRouter>
  );
}

 

 

 

client/login.js

export default function Login() {
  // 아이디 받아오기
  const CLIENT_ID = process.env.REACT_APP_CLIENT_ID;

  const loginRequestHandler = () => {
    // TODO: GitHub로부터 사용자 인증을 위해 GitHub로 이동해야 합니다. 적절한 URL을 입력하세요.
    // OAuth 인증이 완료되면 authorization code와 함께 callback url로 리디렉션 합니다.
    // 참고: <https://docs.github.com/en/free-pro-team@latest/developers/apps/identifying-and-authorizing-users-for-github-apps>
    return window.location.assign(
      `https://github.com/login/oauth/authorize?client_id=${CLIENT_ID}`
    );
  };

...생략
}

.env 파일도 이렇게 클라이언트 ID 를 입력해준다

REACT_APP_CLIENT_ID=???
👉 Api를 사용하거나 인증 관련 기능을 구현할 때,
key를 노출하지 않기 위해 환경 변수 파일에 key를 넣어주고
필요할 때 꺼내올 수 있다.
  • 환경 변수 파일인 .env는 클라이언트와 서버 폴더에 각각 넣어주어야 한다
  • node.js 환경(서버)일 때와 리액트 환경(클라이언트)일 때 설정 방법이 다르다.

🌟 리액트의 경우

//.env
REACT_APP_CLIENT_ID=abcd1234
REACT_APP_CLIENT_SECRET=abcd1234
// ✅ 환경 변수 앞에 REACT_APP_을 붙여주어야 리액트 코드에서 인식할 수 있다.

//Component.js
const CLIENT_ID = process.env.REACT_APP_CLIENT_ID
// ✅ 따로 import 과정 없이 process.env로 어디서든 꺼내쓸 수 있다.

⭐️ node.js의 경우

//.env
CLIENT_ID=abcd1234
CLIENT_SECRET=abcd1234
// ✅ 반드시 REACT_APP과 같은 특정 이름으로 변수명을 지정해주지 않아도 된다.

//callback.js
require('dotenv').config();
// ✅ 반드시 상단에 dotenv를 불러와 config를 실행해야 환경변수를 사용할 수 있다.
const CLIENT_ID = process.env.CLIENT_ID;
const CLIENT_SECRET = process.env.CLIENT_SECRET;
// ✅ 이후에는 process.env로 꺼내쓸 수 있다.

 

 

 

 

client/Mypage.js

export default function Mypage({ accessToken, setIsLogin, setAccessToken }) {
  const [githubUser, setGithubUser] = useState(null);
  const [serverResource, setServerResource] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  const logoutHandler = () => {
    // TODO: /logout을 통해 사용자가 로그아웃되도록 구현하세요.
    // prop으로 받은 Access Token을 이용해 /logout 엔드포인트로 요청을 보내야합니다.
    // 요청이 성공했다면 isLogin 상태를 false로 업데이트해야 합니다.
    // axios delete 의 데이터를 보낼 땐 아래와 같은 방법으로,,,,
    axios
      .delete("<https://localhost:4000/logout>", { data: { accessToken: accessToken } })
      .then((res) => {

        setGithubUser(null)
        setServerResource(null)

        setIsLogin(false);
        setAccessToken('')
      })
      .catch((err) => {
        console.log(err);
      });
  };

  useEffect(() => {
    // TODO: /userinfo를 통해 사용자 정보를 받아오세요.
    // prop으로 받은 Access Token을 이용해 /userinfo 엔드포인트로 요청을 보내야합니다.
    // 응답으로 받은 데이터를 githubUser, serverResource의 상태로 업데이트해야합니다.
    // isLoading 상태를 false로 업데이트해야 합니다.
    axios
      .post("<https://localhost:4000/userinfo>", { accessToken })
      .then((res) => {
        // server/userinfo.js 에서 받아온 데이터
        const { githubUserData, serverResource } = res.data;

        setGithubUser(githubUserData);

        setServerResource(serverResource);

        setIsLoading(false);
      })
      .catch((err) => {
        console.log(err);
      });
  }, [accessToken]);

 

 

 

'Code개발일지' 카테고리의 다른 글

자료구조 - [스택, 큐, 트리, 그래프]  (0) 2023.01.15
Section3 회고  (0) 2023.01.11
Token,, sprint-auth-token  (0) 2023.01.07
[session] sprint-auth-session  (0) 2023.01.07
Session  (0) 2023.01.07