설명:
- Access Token 요청: 클라이언트 (앱)에서 사용자 자격 증명(사용자 이름, 비밀번호)과 함께 client_id, client_secret을 사용하여 인증 서버에 토큰 요청을 보냅니다. 이 요청은 HTTP POST 방식으로 전송됩니다.
- 사용자 인증: 인증 서버에서 사용자의 자격 증명을 검증합니다. 이 과정에서 사용자 이름과 비밀번호의 유효성을 확인합니다.
- Access Token발급: 자격 증명이 유효하면, 서버는 클라이언트에게 access_token(액세스 토큰)을 발급합니다. 이 토큰은 인증된 사용자를 대신하여 API에 접근하는 데 사용됩니다.
- 토큰 수신: 클라이언트는 발급된 access_token을 수신하고, 이후 이를 사용하여 보호된 리소스에 접근할 수 있게 됩니다.
주요 구성 요소:
- Client (App): 토큰을 요청하는 애플리케이션.
- Authorization Server: 사용자 인증 및 토큰 발급을 담당하는 서버.
이러한 흐름을 기반으로 액세스 토큰이 발급되며, 이후 토큰을 이용해 보호된 리소스(API)에 접근할 수 있습니다.

- Endpoint : https://oauth.pp.travelport.com/oauth/oauth20/token
- SessionTimeout : 24시간 (하나 할당 받아 24시간 동안 전체 조회 및 재사용)
- 트래픽 많을 경우 5개 받아 돌아가면서 사용 권장
요청에 포함될 Data
- grant_type : “password” (고정)
- username : 제공된 userName (예 : T11111111)
- password : 제공된 Passwd (예 : PNNNNN)
- client_id : 제공된 id (예 : pp-xxxxxxxxxxxxxxxxxxxxxxxxx1)
- client_secret : 제공된 secret ( 예 : 29aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaae)
- scope : “openid” (고정)
Response Token
eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwianRpIjoibWJ2YTBpNnNub3JoIn0..WCDicZw14vZAdwLN8zeQQA.K85UtNsiShMAZzfoJm8wdqRBSY_t-Egg9O7IIXdi4x3zXGt6BdY3f97JfsI2vpVkEYHl0jhzrmAxjmCW6uPcnxMn6jBni_XaKWwQgaBUVogEyqar0iuVD00q2qfntOunjdsEVWnXIovW_RIatvpO9d3-LRUkFHuzOtEz0evr9yHENYQEmn7p6kKN5fz3uekBXaLt1XOBvfsRFg50rAYsHepQaMYsftEkQNIb8LRqKzk1AB5q7aP9n3lBVFLoeC6jolCEbGAMnxHsJDH66Qf6Zp_QgNf0U81aVf2CNAUP-uk3pC8CWx7c1EDLeP8dQDX-5uAIeMm3FvnK40ltCKJR17QawkoO4H2rfpsT2ak-LyU9wlTJdt1h0JSEqUMMTBs-heWgOj-a8wgzrFepUrGNp-8K44HQDH0UxDeqJ0aaRfWypvsxUfaSvMmWXnrEXQwbwhqDPcPVhWH531LAgMA7cAWP-sUfS2uoZcn05iCXgayDNN37B4YfefGWpwLzeioDTyTY9RBZnn2P1Sf6GdH0H8mkzCioeWxRmxCMkpvmf52qN0ByjU64JM2W7L_3WJC6vPD6i7fT44tIfFmLWcQMk597iqHCGAllIPbFBj_pzlOUWPeoW5vtzL_RJ8ecMoppAiWMxA7urze5CVCrNXn0yXoATlFgWf83Ra2Q8KOnFa66d52sD-GLRfNCj1KS849y1MwxzfYD4BHErAVmYMRFM4MQaG-qGEjLtTjatzZ2ZPgVx71NHfS9JvGKpuniRtfJVmPJfJMbhQNvjqFDH1ozhAtMpLKDlnRmrzdGuco4e2FQ0RfQL9-PpGx8I7yJDXcUNAJTg5j-i_96wJ7IiE209m6NGLxuXIIFz2Xh85GGNB77H372Ugz_tgXxnJTPQYq9I64Cm02zNrT7WY1dxA7gJr3HQ080qNrVkw8vFwjq5CKyxkp219ksioTey8n2UsN5xz5jKGGwWq1qlft2cCugp4nNomwR-FCLaM-96G_EWuu712Oc8F2zEc314INElRGpS7fSn6ymA1538XGJn-mCl8bY3Thos0RvPFdPtu_dPwVXNiZNaQ2eHdEyOkvRHmPsGfAaalUhL4plBmtBdDKiIe8Q8ynbDYrxTWYrbLN2fD9seq_Ydk0QhdfyYtuD7OqXKNDP6hp2lIH2m28bjFywWLLwn8GRJufic19DYuvbuHxMXiVlE1Doiq5wohHDt4JSyctEx6Khgu8oi964edsKdmuPrujOvvfpj2hcNTlZoJZD4DeYvhwAZAxbmIIwlGV8CMm23f0o63DUjWjiqOJyjd8DVwxuxM39w9dP_ZOJFelryV6jZqUGm2QsHuYk5agcKZYeebo2PrqY9KTzlpk8AzQgpYI1kEaTMeAVvl08vV2udp7nm44tSZPXjxtLY2fVJPK74QD8dBoNJ0WhzIBn5qGvpMN4dqHiMdN-KOOpQFF6bgsLb5U7s8crGFyaeSgUw3SkX6qFxd-sgyTfuTVe8nyWD_7-lVahpLjJCYgku8yPjaxfot5_YSL1ab4X-c-ZrUmQiHb2T0gG6rO1tsn8vG6Jk1P8vsUangdKi1ALrFZUSJLmTwAnG1QsUAMapNIuTo17DYRhMfEJHRqI3k5oT0FbyONxNweSZiamk5jksi3GsEsAr2ZQDQSS-IgTr1qRXXVerKIZL_AEtUePigZUro58_edEPbuVRd3bzBEgEJ70gih-KFz5EbI-Eqzn8TS6C3kLA5dBAaVRmwlPt5IVTGivIFVoChwLp66QUoodLyDw1ehyt2dGv6ie67ZSbs4EJnvPpoUN4pGH5RqmZ9IRncPeoVSGL_9WyPfsjQtggomBFoRW4LYGj4zRJboHpGvPSnOJVJIhzzhX-WT9ABubbZsrK_tNxDsYrorqwoCP7WMd_xiQ2POJqmTmhd0x0H044o6RzBLwahzbyMDiGI06Nqktp-EhpilAWWiRpaHMlixzIwvGK8D5VKxxVCdAmm5E6OWzd15zmEc0-nIiym-W-H80tJdaNzNiI88M8VYz0kPcwOxi83CZHRg2KehbAf8d5Y1x53NBHpr37ccjGjnFZ1w0E7EWBK6jIU0OimGEBXEhGZK1qfE9_eu2YWnhWKsda0DAdIJYGiiN3xmMpSqUKJwmR8xc-xqMjD4e6WDBhg6r8Mp48ajEwL9PYSd2RoCnvDlwtPipTpot7nWLmSXPSXUug5qibD1613xwnWXCqk1LLHYHZNTGlMoBnlHn1AfZSFebc-qht3l3Jm9-0ROiv_itBduUP4ZEEZGS_1xeJ9rMzrzxsnxrVRIHPlIGZEk9RmPRF1byD5Gfh081nV29ExjTyBvlmON11Ba93i8jARUS3j1qnqnPFvEWDrDNxs6siZE-SzyVRTX64ep3GEdc0Y2rbqgoncTnVvt_wHuleRIzkBCbeOxL3FLG4YQ6Gw8DP_qQR0QYn1_KRepFRHeohT4HyzVIwDAM67xBF4Enw0cDFxxGjPs3rT8b2g8BN3M0gDHA5rwxk4T3OgUuPEUBNJNIh9ZACshimw6ui7Kz5mSCLeJdOiNW3SmbyoK4Klbla1idXFLLH-q6iWE9TJLbqHFkKwVMD9isO4L2-1Vl5_tTakYlykpy2TV0iBX0l2xz1tQiXVCiQc7cR1zbEgQWIPjSd0AP__4qLTR-Mmonang.wBDSdWVdEnC-Vwk3_4lVhg |
C#
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
using System; using System.Net.Http; using System.Threading.Tasks; using System.Collections.Generic; using Newtonsoft.Json; public class TokenService { private static readonly string tokenEndpoint = "https://oauth.pp.travelport.com/oauth/oauth20/token"; private static readonly string clientId = "your_client_id"; private static readonly string clientSecret = "your_client_secret"; private static readonly string username = "your_username"; private static readonly string password = "your_password"; public async Task<string> GetNDCToken() { using (var client = new HttpClient()) { // 요청에 포함될 폼 데이터 준비 var requestData = new Dictionary<string, string> { { "grant_type", "password" }, { "username", username }, { "password", password }, { "client_id", clientId }, { "client_secret", clientSecret }, { "scope", "openid" } }; var content = new FormUrlEncodedContent(requestData); // POST 요청 전송 var response = await client.PostAsync(tokenEndpoint, content); // 응답이 성공적인지 확인 if (response.IsSuccessStatusCode) { // 응답에서 토큰 값 추출 var jsonResponse = await response.Content.ReadAsStringAsync(); var token = JsonConvert.DeserializeObject<dynamic>(jsonResponse).access_token; return token; } else { Console.WriteLine("Error: Unable to retrieve token."); return string.Empty; } } } public static async Task Main(string[] args) { TokenService service = new TokenService(); string token = await service.GetNDCToken(); if (!string.IsNullOrEmpty(token)) { Console.WriteLine("Access token: " + token); } else { Console.WriteLine("Failed to get access token"); } } } |
Java
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse.BodyHandlers; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import com.fasterxml.jackson.databind.ObjectMapper; public class TokenService { private static final String TOKEN_ENDPOINT = "https://oauth.pp.travelport.com/oauth/oauth20/token"; private static final String CLIENT_ID = "your_client_id"; private static final String CLIENT_SECRET = "your_client_secret"; private static final String USERNAME = "your_username"; private static final String PASSWORD = "your_password"; public CompletableFuture<String> getNDCToken() { HttpClient client = HttpClient.newHttpClient(); // 폼 데이터 준비 Map<String, String> requestData = Map.of( "grant_type", "password", "username", USERNAME, "password", PASSWORD, "client_id", CLIENT_ID, "client_secret", CLIENT_SECRET, "scope", "openid" ); String form = requestData.entrySet() .stream() .map(entry -> entry.getKey() + "=" + entry.getValue()) .collect(Collectors.joining("&")); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(TOKEN_ENDPOINT)) .header("Content-Type", "application/x-www-form-urlencoded") .POST(BodyPublishers.ofString(form)) .build(); // 비동기 POST 요청 전송 return client.sendAsync(request, BodyHandlers.ofString()) .thenApply(response -> { if (response.statusCode() == 200) { try { // 응답에서 토큰 추출 ObjectMapper mapper = new ObjectMapper(); Map<String, Object> jsonResponse = mapper.readValue(response.body(), Map.class); return (String) jsonResponse.get("access_token"); } catch (Exception e) { e.printStackTrace(); } } return ""; }); } public static void main(String[] args) { TokenService service = new TokenService(); service.getNDCToken().thenAccept(token -> { if (!token.isEmpty()) { System.out.println("Access token: " + token); } else { System.out.println("Failed to get access token"); } }); } } |