티스토리 뷰

반응형

문제 발생

Vue.js로 만든 클라이언트에서 OAuth2를 적용하기 위해 hydra를 사용했다.

auth_code 발급까지는 성공했는데, 이 auth_code를 기반으로 access_token을 발급받는데 자꾸 invalid_client 에러가 발생했다.

time="2020-11-10T01:55:43Z" level=error msg="An error occurred" debug="crypto/bcrypt: hashedPassword is not the hash of the given password" description="Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)" error=invalid_client

 

혹시나 client_secret 값이 없어서 발생한건가 싶어 body data에 client_secret도 함께 넣어 요청을 보내면 또 다른 오류가 발생한다.

time="2020-11-10T01:25:05Z" level=error msg="An error occurred" description="Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)" error=invalid_client hint="The OAuth 2.0 Client supports client authentication method \"client_secret_basic\", but method \"client_secret_post\" was requested. You must configure the OAuth 2.0 client's \"token_endpoint_auth_method\" value to accept \"client_secret_post\"."

hydra client를 생성할 때 token_endpoint_auth_method를 client_secret_basic으로 설정했는데, 요청에 secret이 포함되어있어서 오류가 나는 것 같다.

 

참고로 내가 생성한 hydra client를 확인해보면 다음과 같다.

$ hydra clients list \
>     --endpoint https://hydra.trustbloc.local:4445 \
>     --skip-tls-verify
Config file not found because "Config File ".hydra" Not Found in "[/home/ory]""
|     CLIENT ID     | NAME | RESPONSE TYPES |             SCOPE              |                    REDIRECT URIS                     |           GRANT TYPES            | TOKEN ENDPOINT AUTH METHOD |
|-------------------|------|----------------|--------------------------------|------------------------------------------------------|----------------------------------|----------------------------|
| auth-code-client  |      | code,id_token  | StudentCard TravelCard         | https://issuer.trustbloc.local/callback              | authorization_code,refresh_token | client_secret_basic        |
|                   |      |                | PermanentResidentCard          | https://user.trustbloc.local/employID/LoginGroupware |                                  |                            |
|                   |      |                | CertifiedMillTestReport        | https://user.trustbloc.local/employID/LoginWelfare   |                                  |                            |
|                   |      |                | CrudeProductCredential         |                                                      |                                  |                            |
|                   |      |                | UniversityDegreeCredential     |                                                      |                                  |                            |
|                   |      |                | CreditCardStatement            |                                                      |                                  |                            |
|                   |      |                | mDL CreditScore MyData         |                                                      |                                  |                            |
|                   |      |                | EmployeeCard                   |                                                      |                                  |                            |

 

문제 해결

기나긴 구글링과 삽질을 통해 드디어 해결을 했다.
문제는 Token을 발급받기 위해 POST /oauth2/token 요청을 실시할 때, Authorization 헤더 값이 필요하다는 것이다.

아래와 같은 형식으로 Authorization 헤더 값을 넣어 요청을 보내야하는데, 여기서 주의할 점은 <client_id>:<client_secret> 값을 base64로 인코딩해서 보내야한다는 점이다.

Basic window.btoa(<client_id>:<client_secret>)

 

참고로 Vue.js에서 base64로 인코딩하는 방법은 다음과 같다.

window.btoa("base로 인코딩할 문자열");

 

이렇게 해서 요청을 보내면 정상적으로 Token 발급이 완료된다.

Vue.js 상의 코드는 다음과 같다.

...
import qs from "qs";

export default {
    data() {
        return {
            authTokenURL: "https://hydra.trustbloc.local/oauth2/token",
            basicURL: "https://user.trustbloc.local/employID/",
            loginType: "LoginGroupware",
            clientId: "auth-code-client",
            clientSecret: "secret",
            grantType: "authorization_code",
        };
    },
    created: function() {
        ...
        // 요청에 함께 보낼 body data
        var data = {
            grant_type: this.grantType,
            client_id: this.clientId,
            code: code,
            redirect_uri: redirectURI,
        };
        if(!data){
            alert("data가 없습니다.");
            return;
        }
        var queryString = qs.stringify(data);

        // token 발급을 위한 헤더 설정
        // Authorization 헤더: <client_id>:<client_secret> 값을 base64로 인코딩 필요
        var authorization = window.btoa(`${this.clientId}:${this.clientSecret}`);
        var config = {
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
                "Accept": "application/json",
                "Authorization": `Basic ${authorization}`
            }
        };
        
        // POST /oauth2/token 요청
        this.$axios
            .post(`${this.authTokenURL}`, queryString, config)
            .then(response => {
                console.log("response: ", response);
                console.log("response.data: ", response.data);
                console.log("response.data.access_token: ", response.data.access_token);
                console.log("response.data.token_type: ", response.data.token_type);
                console.log("response.data.scope: ", response.data.scope);
            .catch(function(error) {
                console.log("axios.authTokenURL->error");
                alert("OAuth Token 생성에 실패하였습니다.: ", error);
            });

Vue.js는 아직까진 샘플도 많이 없고 구글링해도 자료가 많지 않아서 개발하는 데 오류가 나면 쓸데없이 시간이 오래 걸리는 단점이 있다.

qs로 stringify하는 것도 import를 잘못해서 한참 삽질했다...

어쨋든 간신히 성공...

 

참고 사이트

Ory Hydra - The OAuth 2.0 Token Endpoint

 

REST API | ORY Hydra

Welcome to the ORY Hydra HTTP API documentation. You will find documentation for all HTTP APIs here.

www.ory.sh

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함