SlideShare a Scribd company logo
1 of 27
Download to read offline
Clova Extension – OAuth구현 맛보기
Clova Platform Evangelist
옥상훈
2018-02-28
목차
• Clova extension – OAuth 개요
• Clova extension 계정연동 개발과정
• OAuth 인증서버 개발
Clova extension OAuth 개요
Clova extension 계정연동 서비스 목적
• 써드파티 회원 인증을 거친 사용자에게만 서비스를 제공하려 할 때
• 회원 가입 후 로그인한 사용자에게만 제공
• 써드파티 회원의 속성을 활용하는 서비스를 제공하려고 할 때
• 예) 나의 주문내역, 나의 예약 내역
Clova Extension - OAuth 예시 : 배달의 민족 회원 배달주소, 주문 메뉴설정
• https://blog.naver.com/clova_ai/221188646019
1
2
3
4
5
‘짱구신사’ 익스텐션 데모 시나리오
• 일반 시나리오
• 사용자: 클로바, 짱구신사를 시작해줘
• 익스텐션: 안녕하세요. 짱구신사가 시작되었습니다. 어느 지역 날씨를 알려드릴까요?
• 사용자: 서울 날씨를 알려줘.
• 익스텐션: 서울의 날씨는 맑음입니다.
• 계정연동 시나리오
• 사용자: 클로바, 짱구신사를 시작해줘
• 익스텐션: 안녕하세요. 짱구신사가 시작되었습니다. 어느 지역 날씨를 알려드릴까요?
• 사용자: 우리 동네 날씨 어때? (지역정보 없는 발화가 입력되면 회원정보에 설정된 지역명 조회 )
• 익스텐션: ***의 날씨는 맑음입니다.
Clova Extension - OAuth 흐름
1
2
3 4
5
1) Clova console 상에 익스텐션 tester로 등록되어 있으면 노출
2) 계정연동버튼
• Clova console에 계정연결여부가 ‘Y’이면 익스텐션 정보에 ’계정연동’버튼 노출
• 버튼을 누르면 Clova에서 OAuth2스펙에 따라 ‘로그인URL( Authorization URL ) ’로 설정된 웹페이지호출
3) 로그인 화면
• 써드파티 인증서버에서 제공하는 로그인 화면으로 회원 인증 진행
• 회원 인증에 성공하면, 2)단계에서 Clova가 넘겨준 OAuth 요청변수들을 ‘Access Token URI’ 로 요청전달
4) 접근권한 허용 화면
• 써드파티 인증서버에서 제공하는 접근권한 허용 화면
• 접근권한 허용하면 Clova가 넘겨준 redirect_uri로 이동 à 화면 5로 전환
5) 연동상태 허용 화면
• Clova에서는 익스텐션 서버로 요청을 보낼 때 accessToken 값을 같이 전송
Clova extension 계정연동 개발과정
Clova extension 계정연동 개발 과정
• Clova console에 익스텐션 등록
• 개발자콘솔에 기본정보, 서버정보, 계정연동 정보 등록
• 인터렉션 모델 구성
• 사용자 대화 시나리오 및 대화에 따른 처리할 Intent 및 slot 등록
• 익스텐션 API 서버 개발
• Clova로부터 Intent 요청을 받으면 이에 응답하는 API 개발
• 특정 API는 접근토큰이 있어야 응답가능하게 변경
• 인증 API 서버 개발
• Clova로부터 계정연동 페이지를 로딩하면 로그인페이지를 제공하고, 로그인 완료시 접근토큰을 발행
Clova console에 익스텐션 등록 - Extension 정보
Clova console에 익스텐션 등록 – 서버 연동 설정 - 1
Clova console에 익스텐션 등록 – 서버 연동 설정 - 2
OAuth 서버의 Endopoint URL à Controller에 구현
인터렉션 모델 구성
익스텐션 API 서버 개발
• 익스텐션서버
• REST API 서버로서, Clova platform은 Clova console에 등록한 REST API 서버URL로 응답과 요청을 주고
받습니다.
• Clova platform은 1) 익스텐션 실행 2) 인텐트 실행 3) 익스텐션 종료라는 3가지 type의 요청을 보내고, 익스
텐션 서버는 여기에 맞게 응답을 하면 됩니다.
• 익스텐션 서버는 https로 외부망으로 통신할 수 있는 서버이어야 하며, 포트는 80 또는 443로만 통신합니다.
서버가 처리해야할 작업
• Clova 요청 메시지의 request type에 따라 지정된 포맷의 응답 리
턴
• Request type
• LaunchRequest : 익스텐션의 시작 (“짱구박사 시작해줘” 했을 경우)
• SessionEndedRequest : 익스텐션의 종료 (“종료해줘” )
• IntentRequest
• Custom Intent à 개발자 콘솔에 입력한 Intent 와 Slot
• Built-in Intent à
https://developers.naver.com/console/clova/guide/CEK/References/CEK_API.md#cek-api-레퍼런스
OAuth 인증 API 서버 개발 – 주요 역할
• 회원 로그인
• 로그인 화면 제공 à Clova console에 등록한 ‘로그인 URL’에 해당
• 회원 인증 à 로그인 화면에서 입력한 id, pw에 대해 회원 인증 로직 구현
•
• 접근 토큰 발급
• 접근토큰 발행 대상 à Clova console에 등록한 ‘클라이언트 ID’와 ‘클라이언트
secret’이 대상
• Clova 는 Consumer, 써드파티 인증서버는 Provider 역할임
• 접근토큰 발행 : 회원 인증에 성공하면 Clova console에 등록한 ‘Access token
URI’로 요청을 보내고, 여기서 접근토큰을 발급 à 이후 Redirect URL로 이동
(https://prod-ni-cic.clova.ai/v1/al/token 로 고정되어 있음)
스펙: https://developers.naver.com/console/clova/guide/CEK/Guides/Link_User_Account.md
OAuth 인증 API 서버 개발 – 주요 작업
• 서버 구성
• 개발편의상 API 서버와 OAuth 서버는 하나의 서버로 제공
• 회원 정보 관리
• 회원 정보 및 인증 처리는 hard code로 처리
• 개발 환경
• SpringBoot 기반 : Web (API 서버) + Security (OAuth 서버)
OAuth 인증 API 서버 개발 – extension 처리 API
@RequestMapping(value = "/clova/extension", method= RequestMethod.POST, produces = "application/json" )
@ResponseBody
public ResponseEntity<MyExtensionMessage> weather (@RequestBody Map<String, Object> map) {
Map m = (HashMap)map.get("request");
String type = (String) m.get("type");
MyExtensionMessage mm = null;
if(type.equals("LaunchRequest")) { // extension 시작
mm= new MyExtensionMessage("안녕, 짱구 신사를 시작합니다. 어느 지역 날씨를 알려드릴까요 ?", false);
} else if (type.equals("IntentRequest")) { // extension의 인텐트 시작
…...........
} else if (type.equals(”SessionEndedRequest")) { // extension 종료
mm= new MyExtensionMessage("짱구 날씨를 종료합니다.", true);
}
return new ResponseEntity<MyExtensionMessage>(mm, HttpStatus.OK);
}
OAuth 인증 API 서버 개발 – extension 처리 API
if (intentName.equals("weatherIntent")) {
if (slots != null) {
Map myslot = (HashMap) slots.get("areaSlot");
if(myslot != null ) {
slotName = (String) myslot.get("name");
slotValue = (String) myslot.get("value");
System.out.println("slotName===" + slotName);
System.out.println("slotValue===" + slotValue);
} else {
// slot 이 없으면 사용자 정보에서
// 접근토큰을 이용해 사용자의 지역 정보 조회
slotValue = getUserArea(accessToken);
}
} else {
slotValue = getUserArea(accessToken);
}
mm = new MyExtensionMessage(intentName, slotValue + "의 날씨는 점점 따뜻해 지고 있어요.", false, "PlainText");
// Built-in Intent 처리
} else if (intentName.equals("Clova.YesIntent")) {
mm = new MyExtensionMessage(intentName, "예 라고 하셨나요?", true, "PlainText");
} else if (intentName.equals("Clova.NoIntent")) {
mm = new MyExtensionMessage(intentName, "노 라고 하셨나요?", true, "PlainText");
} else if (intentName.equals("Clova.GuideIntent")) {
mm = new MyExtensionMessage("hearTestIntent", "진주 날씨는 어때라고 해보세요", false, "PlainText");
} else if (intentName.equals("Clova.CancelIntent")) {
mm = new MyExtensionMessage("hearTestIntent", "짱구 신사 실행을 취소합니다. 안녕", true, "PlainText");
}
Extension 응답 message
처리 클래스
public class MyExtensionMessage {
public String version = "1.0";
public Map<String, Object> sessionAttributes = new HashMap();
public MyResponse response = null;
public MyExtensionMessage(String message, boolean session) {
MyResponseValue value = new MyResponseValue();
value.value = message;
if(!session) {
sessionAttributes.put("intent", "zzanguWeather");
}
MyResponse response = new MyResponse();
response.shouldEndSession = session;
response.outputSpeech.put("type", "SimpleSpeech");
response.outputSpeech.put("values", value);
this.response = response;
}
public static class MyResponse {
public Map<String, Object> outputSpeech = new
HashMap<String, Object>();
public Map<String, Map> card = new HashMap<String, Map>();
public ArrayList<String> directives = new ArrayList<String>();
public boolean shouldEndSession = false;
}
public static class MyResponseValue {
public String type = "PlainText";
public String lang = "ko";
public String value;
}
}
OAuth 인증 API 서버 개발 – 인증 처리 API
// 로그인 화면 html 로딩
@GetMapping("/clova/login")
@ResponseBody
public ModelAndView loginForm(HttpServletResponse httpServletResponse, @RequestParam("state") String state ) {
STATE_STRING = state;
return new ModelAndView("redirect:" + "/login.html");
}
@GetMapping("/clova/config")
@ResponseBody
public ModelAndView config( ) {
return new ModelAndView("redirect:" + "/config.html");
}
// login.html 에서 로그인 버튼 클릭시 접근토큰 발급 처리 (id, pw가 맞다고 가정 )
@PostMapping("/clova/login/check")
@ResponseBody
public void loginCheck(HttpServletResponse httpServletResponse, @RequestParam("userid") String userid, @RequestParam("passwd") String passwd,
@RequestParam("state") String state) throws IOException {
String redirect_uri = "https://prod-ni-cic.clova.ai/v1/al/token";
String url = "http://user:test@okgosu.net/oauth/authorize?response_type=code&client_id=clova&redirect_uri=" + redirect_uri +
"&scope=read&state="+STATE_STRING;
httpServletResponse.sendRedirect(url);
}
OAuth 인증 API 서버 개발 – 회원 API
@RequestMapping(value = "/clova/member", method= RequestMethod.POST,
produces = "application/json" )
@ResponseStatus(HttpStatus.CREATED)
Member create(@RequestBody Member member) {
return service.create(member);
}
@RequestMapping(value = "/clova/member", method=
RequestMethod.GET,produces = "application/json" )
Collection<Member> readList() {
return service.findAll();
}
@RequestMapping(value = "/clova/member/{id}", method= RequestMethod.GET,
produces = "application/json" )
ResponseEntity<Member> read(@PathVariable Integer id) {
Member b = service.findById(id);
return new ResponseEntity<Member>(b, HttpStatus.OK);
}
OAuth 인증 API 서버 개발 – 회원 관리 등록
@Service
public class MemberService {
private ConcurrentMap<Integer, Member> repo = new ConcurrentHashMap<>();
private AtomicInteger maxId = new AtomicInteger(0);
public MemberService() {
Member member = new Member("okgosu", "안드로메다");
Integer id = maxId.addAndGet(1);
member.setId(id);
repo.put(id, member);
}
public Member findById(Integer id) {
Member b = repo.get(id);
return b;
}
public boolean update(Member member) {
Member old = repo.put(member.getId(), member);
return old != null;
}
public Member create(Member member) {
Integer id = maxId.addAndGet(1);
member.setId(id);
repo.put(id, member);
return member;
}
public boolean delete(Integer id) {
Member old = repo.remove(id);
return old != null;
}
public Collection<Member> findAll() {
return repo.values();
}
}
Spring
Security
설정
@EnableResourceServer
@EnableAuthorizationServer
@SpringBootApplication
public class DemoApplication extends ResourceServerConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/clova/member").authenticated();
}
}
# application.properties
security.user.name=user
security.user.password=test
# client id, secret
security.oauth2.client.client-id=clova
security.oauth2.client.client-secret=clova123
security.enable-csrf=false
security.oauth2.client.scope=read
server.port=80
Thank you.
제휴문의: dl_clova_partnership@navercorp.com
Appendix.
• Clova Platform 발표자료 : https://www.slideshare.net/clovaplatform
• Clova 플랫폼 개발자 문서 : https://developers.naver.com/console/clova/guide/
• Design 챕터 / Clova Extensions Kit 챕터 / Clova Developer Console 챕터 참고
• 튜토리얼 및 샘플 코드 참고
• 샘플 코드 Github
• 마법 구슬 : https://github.com/naver/clova-extension-sample-magicball
• 빗소리 : https://github.com/naver/clova-extension-sample-rainsound
• 주사위 놀이 : https://github.com/naver/clova-extension-sample-dice
• 코인 헬퍼 : https://github.com/naver/clova-extension-sample-coinhelper

More Related Content

Similar to Clova extension에서 OAuth 계정 연동 구현

Clova extension A to Z
Clova extension A to ZClova extension A to Z
Clova extension A to ZClova Platform
 
Hyperledger fabric - tuna fishing analysis
Hyperledger fabric - tuna fishing analysisHyperledger fabric - tuna fishing analysis
Hyperledger fabric - tuna fishing analysis병준 김
 
Clova Extension 기획, 설계 & 서버 개발 Basic
Clova Extension 기획, 설계 & 서버 개발 BasicClova Extension 기획, 설계 & 서버 개발 Basic
Clova Extension 기획, 설계 & 서버 개발 BasicClova Platform
 
Amazon Cognito를 활용한 모바일 인증 및 보안, 자원 접근 제어 기법 - AWS Summit Seoul 2017
Amazon Cognito를 활용한 모바일 인증 및 보안, 자원 접근 제어 기법 - AWS Summit Seoul 2017Amazon Cognito를 활용한 모바일 인증 및 보안, 자원 접근 제어 기법 - AWS Summit Seoul 2017
Amazon Cognito를 활용한 모바일 인증 및 보안, 자원 접근 제어 기법 - AWS Summit Seoul 2017Amazon Web Services Korea
 
HTTPS를 이용한 챗봇 웹 어플리케이션
HTTPS를 이용한 챗봇 웹 어플리케이션HTTPS를 이용한 챗봇 웹 어플리케이션
HTTPS를 이용한 챗봇 웹 어플리케이션Lee Geonhee
 
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 GamingCloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 GamingAmazon Web Services Korea
 
Naver 오픈api-마이그레이션가이드 20160913-리뷰
Naver 오픈api-마이그레이션가이드 20160913-리뷰Naver 오픈api-마이그레이션가이드 20160913-리뷰
Naver 오픈api-마이그레이션가이드 20160913-리뷰NAVER D2
 
AWS 마켓플레이스 성공 런칭을 위한 핵심 기술 (이경수, AWS 솔루션즈아키텍트) :: AWS TechShift 2018
AWS 마켓플레이스 성공 런칭을 위한 핵심 기술 (이경수, AWS 솔루션즈아키텍트) :: AWS TechShift 2018AWS 마켓플레이스 성공 런칭을 위한 핵심 기술 (이경수, AWS 솔루션즈아키텍트) :: AWS TechShift 2018
AWS 마켓플레이스 성공 런칭을 위한 핵심 기술 (이경수, AWS 솔루션즈아키텍트) :: AWS TechShift 2018Amazon Web Services Korea
 
구글 기술을 이용한 모바일 클라우드 애플리케이션 개발
 구글 기술을 이용한 모바일 클라우드 애플리케이션 개발 구글 기술을 이용한 모바일 클라우드 애플리케이션 개발
구글 기술을 이용한 모바일 클라우드 애플리케이션 개발LGU+
 
Service mesh(istio) monitoring
Service mesh(istio) monitoringService mesh(istio) monitoring
Service mesh(istio) monitoringJeong-Ho Na
 
[112]clova platform 인공지능을 엮는 기술
[112]clova platform 인공지능을 엮는 기술[112]clova platform 인공지능을 엮는 기술
[112]clova platform 인공지능을 엮는 기술NAVER D2
 
ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0병준 김
 
AWS CLOUD 2018- 관리형 Kubernetes 지원과 새로운 컨테이너 서비스 Amazon Fargate 소개 (정영준 솔루션즈 아...
AWS CLOUD 2018- 관리형 Kubernetes 지원과 새로운 컨테이너 서비스 Amazon Fargate 소개 (정영준 솔루션즈 아...AWS CLOUD 2018- 관리형 Kubernetes 지원과 새로운 컨테이너 서비스 Amazon Fargate 소개 (정영준 솔루션즈 아...
AWS CLOUD 2018- 관리형 Kubernetes 지원과 새로운 컨테이너 서비스 Amazon Fargate 소개 (정영준 솔루션즈 아...Amazon Web Services Korea
 
Google Cloud Platform - Apigee
Google Cloud Platform - ApigeeGoogle Cloud Platform - Apigee
Google Cloud Platform - Apigeebliexsoft
 
우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?Arawn Park
 
TXGX 2019_Jesse_Klaytn API Service
TXGX 2019_Jesse_Klaytn API ServiceTXGX 2019_Jesse_Klaytn API Service
TXGX 2019_Jesse_Klaytn API ServiceKlaytn
 
[제3회 스포카콘] React + TypeScript + GraphQL 으로 시작하는 Web Front-End
[제3회 스포카콘] React + TypeScript + GraphQL 으로 시작하는 Web Front-End[제3회 스포카콘] React + TypeScript + GraphQL 으로 시작하는 Web Front-End
[제3회 스포카콘] React + TypeScript + GraphQL 으로 시작하는 Web Front-End우현 김
 
Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기GunHee Lee
 
Dropbox와 같은 시스템은 파일을 어떻게 저장할까?
Dropbox와 같은 시스템은 파일을 어떻게 저장할까?Dropbox와 같은 시스템은 파일을 어떻게 저장할까?
Dropbox와 같은 시스템은 파일을 어떻게 저장할까?nexusz99
 

Similar to Clova extension에서 OAuth 계정 연동 구현 (20)

Clova extension A to Z
Clova extension A to ZClova extension A to Z
Clova extension A to Z
 
Hyperledger fabric - tuna fishing analysis
Hyperledger fabric - tuna fishing analysisHyperledger fabric - tuna fishing analysis
Hyperledger fabric - tuna fishing analysis
 
Clova Extension 기획, 설계 & 서버 개발 Basic
Clova Extension 기획, 설계 & 서버 개발 BasicClova Extension 기획, 설계 & 서버 개발 Basic
Clova Extension 기획, 설계 & 서버 개발 Basic
 
Amazon Cognito를 활용한 모바일 인증 및 보안, 자원 접근 제어 기법 - AWS Summit Seoul 2017
Amazon Cognito를 활용한 모바일 인증 및 보안, 자원 접근 제어 기법 - AWS Summit Seoul 2017Amazon Cognito를 활용한 모바일 인증 및 보안, 자원 접근 제어 기법 - AWS Summit Seoul 2017
Amazon Cognito를 활용한 모바일 인증 및 보안, 자원 접근 제어 기법 - AWS Summit Seoul 2017
 
HTTPS를 이용한 챗봇 웹 어플리케이션
HTTPS를 이용한 챗봇 웹 어플리케이션HTTPS를 이용한 챗봇 웹 어플리케이션
HTTPS를 이용한 챗봇 웹 어플리케이션
 
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 GamingCloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
CloudWatch 성능 모니터링과 신속한 대응을 위한 노하우 - 박선용 솔루션즈 아키텍트:: AWS Cloud Track 3 Gaming
 
Naver 오픈api-마이그레이션가이드 20160913-리뷰
Naver 오픈api-마이그레이션가이드 20160913-리뷰Naver 오픈api-마이그레이션가이드 20160913-리뷰
Naver 오픈api-마이그레이션가이드 20160913-리뷰
 
AWS 마켓플레이스 성공 런칭을 위한 핵심 기술 (이경수, AWS 솔루션즈아키텍트) :: AWS TechShift 2018
AWS 마켓플레이스 성공 런칭을 위한 핵심 기술 (이경수, AWS 솔루션즈아키텍트) :: AWS TechShift 2018AWS 마켓플레이스 성공 런칭을 위한 핵심 기술 (이경수, AWS 솔루션즈아키텍트) :: AWS TechShift 2018
AWS 마켓플레이스 성공 런칭을 위한 핵심 기술 (이경수, AWS 솔루션즈아키텍트) :: AWS TechShift 2018
 
구글 기술을 이용한 모바일 클라우드 애플리케이션 개발
 구글 기술을 이용한 모바일 클라우드 애플리케이션 개발 구글 기술을 이용한 모바일 클라우드 애플리케이션 개발
구글 기술을 이용한 모바일 클라우드 애플리케이션 개발
 
Service mesh(istio) monitoring
Service mesh(istio) monitoringService mesh(istio) monitoring
Service mesh(istio) monitoring
 
[112]clova platform 인공지능을 엮는 기술
[112]clova platform 인공지능을 엮는 기술[112]clova platform 인공지능을 엮는 기술
[112]clova platform 인공지능을 엮는 기술
 
ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0
 
OpenStack Swift Debugging
OpenStack Swift DebuggingOpenStack Swift Debugging
OpenStack Swift Debugging
 
AWS CLOUD 2018- 관리형 Kubernetes 지원과 새로운 컨테이너 서비스 Amazon Fargate 소개 (정영준 솔루션즈 아...
AWS CLOUD 2018- 관리형 Kubernetes 지원과 새로운 컨테이너 서비스 Amazon Fargate 소개 (정영준 솔루션즈 아...AWS CLOUD 2018- 관리형 Kubernetes 지원과 새로운 컨테이너 서비스 Amazon Fargate 소개 (정영준 솔루션즈 아...
AWS CLOUD 2018- 관리형 Kubernetes 지원과 새로운 컨테이너 서비스 Amazon Fargate 소개 (정영준 솔루션즈 아...
 
Google Cloud Platform - Apigee
Google Cloud Platform - ApigeeGoogle Cloud Platform - Apigee
Google Cloud Platform - Apigee
 
우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?
 
TXGX 2019_Jesse_Klaytn API Service
TXGX 2019_Jesse_Klaytn API ServiceTXGX 2019_Jesse_Klaytn API Service
TXGX 2019_Jesse_Klaytn API Service
 
[제3회 스포카콘] React + TypeScript + GraphQL 으로 시작하는 Web Front-End
[제3회 스포카콘] React + TypeScript + GraphQL 으로 시작하는 Web Front-End[제3회 스포카콘] React + TypeScript + GraphQL 으로 시작하는 Web Front-End
[제3회 스포카콘] React + TypeScript + GraphQL 으로 시작하는 Web Front-End
 
Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기
 
Dropbox와 같은 시스템은 파일을 어떻게 저장할까?
Dropbox와 같은 시스템은 파일을 어떻게 저장할까?Dropbox와 같은 시스템은 파일을 어떻게 저장할까?
Dropbox와 같은 시스템은 파일을 어떻게 저장할까?
 

Clova extension에서 OAuth 계정 연동 구현

  • 1. Clova Extension – OAuth구현 맛보기 Clova Platform Evangelist 옥상훈 2018-02-28
  • 2. 목차 • Clova extension – OAuth 개요 • Clova extension 계정연동 개발과정 • OAuth 인증서버 개발
  • 4. Clova extension 계정연동 서비스 목적 • 써드파티 회원 인증을 거친 사용자에게만 서비스를 제공하려 할 때 • 회원 가입 후 로그인한 사용자에게만 제공 • 써드파티 회원의 속성을 활용하는 서비스를 제공하려고 할 때 • 예) 나의 주문내역, 나의 예약 내역
  • 5. Clova Extension - OAuth 예시 : 배달의 민족 회원 배달주소, 주문 메뉴설정 • https://blog.naver.com/clova_ai/221188646019 1 2 3 4 5
  • 6. ‘짱구신사’ 익스텐션 데모 시나리오 • 일반 시나리오 • 사용자: 클로바, 짱구신사를 시작해줘 • 익스텐션: 안녕하세요. 짱구신사가 시작되었습니다. 어느 지역 날씨를 알려드릴까요? • 사용자: 서울 날씨를 알려줘. • 익스텐션: 서울의 날씨는 맑음입니다. • 계정연동 시나리오 • 사용자: 클로바, 짱구신사를 시작해줘 • 익스텐션: 안녕하세요. 짱구신사가 시작되었습니다. 어느 지역 날씨를 알려드릴까요? • 사용자: 우리 동네 날씨 어때? (지역정보 없는 발화가 입력되면 회원정보에 설정된 지역명 조회 ) • 익스텐션: ***의 날씨는 맑음입니다.
  • 7. Clova Extension - OAuth 흐름 1 2 3 4 5
  • 8. 1) Clova console 상에 익스텐션 tester로 등록되어 있으면 노출 2) 계정연동버튼 • Clova console에 계정연결여부가 ‘Y’이면 익스텐션 정보에 ’계정연동’버튼 노출 • 버튼을 누르면 Clova에서 OAuth2스펙에 따라 ‘로그인URL( Authorization URL ) ’로 설정된 웹페이지호출 3) 로그인 화면 • 써드파티 인증서버에서 제공하는 로그인 화면으로 회원 인증 진행 • 회원 인증에 성공하면, 2)단계에서 Clova가 넘겨준 OAuth 요청변수들을 ‘Access Token URI’ 로 요청전달 4) 접근권한 허용 화면 • 써드파티 인증서버에서 제공하는 접근권한 허용 화면 • 접근권한 허용하면 Clova가 넘겨준 redirect_uri로 이동 à 화면 5로 전환 5) 연동상태 허용 화면 • Clova에서는 익스텐션 서버로 요청을 보낼 때 accessToken 값을 같이 전송
  • 10. Clova extension 계정연동 개발 과정 • Clova console에 익스텐션 등록 • 개발자콘솔에 기본정보, 서버정보, 계정연동 정보 등록 • 인터렉션 모델 구성 • 사용자 대화 시나리오 및 대화에 따른 처리할 Intent 및 slot 등록 • 익스텐션 API 서버 개발 • Clova로부터 Intent 요청을 받으면 이에 응답하는 API 개발 • 특정 API는 접근토큰이 있어야 응답가능하게 변경 • 인증 API 서버 개발 • Clova로부터 계정연동 페이지를 로딩하면 로그인페이지를 제공하고, 로그인 완료시 접근토큰을 발행
  • 11. Clova console에 익스텐션 등록 - Extension 정보
  • 12. Clova console에 익스텐션 등록 – 서버 연동 설정 - 1
  • 13. Clova console에 익스텐션 등록 – 서버 연동 설정 - 2 OAuth 서버의 Endopoint URL à Controller에 구현
  • 15. 익스텐션 API 서버 개발 • 익스텐션서버 • REST API 서버로서, Clova platform은 Clova console에 등록한 REST API 서버URL로 응답과 요청을 주고 받습니다. • Clova platform은 1) 익스텐션 실행 2) 인텐트 실행 3) 익스텐션 종료라는 3가지 type의 요청을 보내고, 익스 텐션 서버는 여기에 맞게 응답을 하면 됩니다. • 익스텐션 서버는 https로 외부망으로 통신할 수 있는 서버이어야 하며, 포트는 80 또는 443로만 통신합니다.
  • 16. 서버가 처리해야할 작업 • Clova 요청 메시지의 request type에 따라 지정된 포맷의 응답 리 턴 • Request type • LaunchRequest : 익스텐션의 시작 (“짱구박사 시작해줘” 했을 경우) • SessionEndedRequest : 익스텐션의 종료 (“종료해줘” ) • IntentRequest • Custom Intent à 개발자 콘솔에 입력한 Intent 와 Slot • Built-in Intent à https://developers.naver.com/console/clova/guide/CEK/References/CEK_API.md#cek-api-레퍼런스
  • 17. OAuth 인증 API 서버 개발 – 주요 역할 • 회원 로그인 • 로그인 화면 제공 à Clova console에 등록한 ‘로그인 URL’에 해당 • 회원 인증 à 로그인 화면에서 입력한 id, pw에 대해 회원 인증 로직 구현 • • 접근 토큰 발급 • 접근토큰 발행 대상 à Clova console에 등록한 ‘클라이언트 ID’와 ‘클라이언트 secret’이 대상 • Clova 는 Consumer, 써드파티 인증서버는 Provider 역할임 • 접근토큰 발행 : 회원 인증에 성공하면 Clova console에 등록한 ‘Access token URI’로 요청을 보내고, 여기서 접근토큰을 발급 à 이후 Redirect URL로 이동 (https://prod-ni-cic.clova.ai/v1/al/token 로 고정되어 있음) 스펙: https://developers.naver.com/console/clova/guide/CEK/Guides/Link_User_Account.md
  • 18. OAuth 인증 API 서버 개발 – 주요 작업 • 서버 구성 • 개발편의상 API 서버와 OAuth 서버는 하나의 서버로 제공 • 회원 정보 관리 • 회원 정보 및 인증 처리는 hard code로 처리 • 개발 환경 • SpringBoot 기반 : Web (API 서버) + Security (OAuth 서버)
  • 19. OAuth 인증 API 서버 개발 – extension 처리 API @RequestMapping(value = "/clova/extension", method= RequestMethod.POST, produces = "application/json" ) @ResponseBody public ResponseEntity<MyExtensionMessage> weather (@RequestBody Map<String, Object> map) { Map m = (HashMap)map.get("request"); String type = (String) m.get("type"); MyExtensionMessage mm = null; if(type.equals("LaunchRequest")) { // extension 시작 mm= new MyExtensionMessage("안녕, 짱구 신사를 시작합니다. 어느 지역 날씨를 알려드릴까요 ?", false); } else if (type.equals("IntentRequest")) { // extension의 인텐트 시작 …........... } else if (type.equals(”SessionEndedRequest")) { // extension 종료 mm= new MyExtensionMessage("짱구 날씨를 종료합니다.", true); } return new ResponseEntity<MyExtensionMessage>(mm, HttpStatus.OK); }
  • 20. OAuth 인증 API 서버 개발 – extension 처리 API if (intentName.equals("weatherIntent")) { if (slots != null) { Map myslot = (HashMap) slots.get("areaSlot"); if(myslot != null ) { slotName = (String) myslot.get("name"); slotValue = (String) myslot.get("value"); System.out.println("slotName===" + slotName); System.out.println("slotValue===" + slotValue); } else { // slot 이 없으면 사용자 정보에서 // 접근토큰을 이용해 사용자의 지역 정보 조회 slotValue = getUserArea(accessToken); } } else { slotValue = getUserArea(accessToken); } mm = new MyExtensionMessage(intentName, slotValue + "의 날씨는 점점 따뜻해 지고 있어요.", false, "PlainText"); // Built-in Intent 처리 } else if (intentName.equals("Clova.YesIntent")) { mm = new MyExtensionMessage(intentName, "예 라고 하셨나요?", true, "PlainText"); } else if (intentName.equals("Clova.NoIntent")) { mm = new MyExtensionMessage(intentName, "노 라고 하셨나요?", true, "PlainText"); } else if (intentName.equals("Clova.GuideIntent")) { mm = new MyExtensionMessage("hearTestIntent", "진주 날씨는 어때라고 해보세요", false, "PlainText"); } else if (intentName.equals("Clova.CancelIntent")) { mm = new MyExtensionMessage("hearTestIntent", "짱구 신사 실행을 취소합니다. 안녕", true, "PlainText"); }
  • 21. Extension 응답 message 처리 클래스 public class MyExtensionMessage { public String version = "1.0"; public Map<String, Object> sessionAttributes = new HashMap(); public MyResponse response = null; public MyExtensionMessage(String message, boolean session) { MyResponseValue value = new MyResponseValue(); value.value = message; if(!session) { sessionAttributes.put("intent", "zzanguWeather"); } MyResponse response = new MyResponse(); response.shouldEndSession = session; response.outputSpeech.put("type", "SimpleSpeech"); response.outputSpeech.put("values", value); this.response = response; } public static class MyResponse { public Map<String, Object> outputSpeech = new HashMap<String, Object>(); public Map<String, Map> card = new HashMap<String, Map>(); public ArrayList<String> directives = new ArrayList<String>(); public boolean shouldEndSession = false; } public static class MyResponseValue { public String type = "PlainText"; public String lang = "ko"; public String value; } }
  • 22. OAuth 인증 API 서버 개발 – 인증 처리 API // 로그인 화면 html 로딩 @GetMapping("/clova/login") @ResponseBody public ModelAndView loginForm(HttpServletResponse httpServletResponse, @RequestParam("state") String state ) { STATE_STRING = state; return new ModelAndView("redirect:" + "/login.html"); } @GetMapping("/clova/config") @ResponseBody public ModelAndView config( ) { return new ModelAndView("redirect:" + "/config.html"); } // login.html 에서 로그인 버튼 클릭시 접근토큰 발급 처리 (id, pw가 맞다고 가정 ) @PostMapping("/clova/login/check") @ResponseBody public void loginCheck(HttpServletResponse httpServletResponse, @RequestParam("userid") String userid, @RequestParam("passwd") String passwd, @RequestParam("state") String state) throws IOException { String redirect_uri = "https://prod-ni-cic.clova.ai/v1/al/token"; String url = "http://user:test@okgosu.net/oauth/authorize?response_type=code&client_id=clova&redirect_uri=" + redirect_uri + "&scope=read&state="+STATE_STRING; httpServletResponse.sendRedirect(url); }
  • 23. OAuth 인증 API 서버 개발 – 회원 API @RequestMapping(value = "/clova/member", method= RequestMethod.POST, produces = "application/json" ) @ResponseStatus(HttpStatus.CREATED) Member create(@RequestBody Member member) { return service.create(member); } @RequestMapping(value = "/clova/member", method= RequestMethod.GET,produces = "application/json" ) Collection<Member> readList() { return service.findAll(); } @RequestMapping(value = "/clova/member/{id}", method= RequestMethod.GET, produces = "application/json" ) ResponseEntity<Member> read(@PathVariable Integer id) { Member b = service.findById(id); return new ResponseEntity<Member>(b, HttpStatus.OK); }
  • 24. OAuth 인증 API 서버 개발 – 회원 관리 등록 @Service public class MemberService { private ConcurrentMap<Integer, Member> repo = new ConcurrentHashMap<>(); private AtomicInteger maxId = new AtomicInteger(0); public MemberService() { Member member = new Member("okgosu", "안드로메다"); Integer id = maxId.addAndGet(1); member.setId(id); repo.put(id, member); } public Member findById(Integer id) { Member b = repo.get(id); return b; } public boolean update(Member member) { Member old = repo.put(member.getId(), member); return old != null; } public Member create(Member member) { Integer id = maxId.addAndGet(1); member.setId(id); repo.put(id, member); return member; } public boolean delete(Integer id) { Member old = repo.remove(id); return old != null; } public Collection<Member> findAll() { return repo.values(); } }
  • 25. Spring Security 설정 @EnableResourceServer @EnableAuthorizationServer @SpringBootApplication public class DemoApplication extends ResourceServerConfigurerAdapter { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/clova/member").authenticated(); } } # application.properties security.user.name=user security.user.password=test # client id, secret security.oauth2.client.client-id=clova security.oauth2.client.client-secret=clova123 security.enable-csrf=false security.oauth2.client.scope=read server.port=80
  • 27. Appendix. • Clova Platform 발표자료 : https://www.slideshare.net/clovaplatform • Clova 플랫폼 개발자 문서 : https://developers.naver.com/console/clova/guide/ • Design 챕터 / Clova Extensions Kit 챕터 / Clova Developer Console 챕터 참고 • 튜토리얼 및 샘플 코드 참고 • 샘플 코드 Github • 마법 구슬 : https://github.com/naver/clova-extension-sample-magicball • 빗소리 : https://github.com/naver/clova-extension-sample-rainsound • 주사위 놀이 : https://github.com/naver/clova-extension-sample-dice • 코인 헬퍼 : https://github.com/naver/clova-extension-sample-coinhelper