Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
JWT와 Flask, PyJWT로 인증 API 서버 만들기
Search
Junho Kim
August 25, 2018
Programming
2.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
JWT와 Flask, PyJWT로 인증 API 서버 만들기
PyCon 2018 KR Tutorial slide
Junho Kim
August 25, 2018
Other Decks in Programming
See All in Programming
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
430
機械に任せるテスト、人が見るテスト ⽣成AIで引き直した、運⽤保守フェーズの線引き
dske104
0
190
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
5.2k
JAWS-UG 東京支部が始める、JAWS-UG支部コラボ / JAWS-UG lunchtime LT Collaboration
y0hgi
0
280
Domain-Driven Transformation
hschwentner
2
2.3k
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
170
Workers Cache を知る
syumai
0
370
外から家のPCの電源入れたい!をPHPで解決する
kawashimo0
1
140
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
170
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
610
Agents on Rails - Rails at Scale 2026
irinanazarova
0
560
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
320
Featured
See All Featured
The World Runs on Bad Software
bkeepers
PRO
72
12k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Fireside Chat
paigeccino
43
4.1k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
320
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
850
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
ラッコキーワード サービス紹介資料
rakko
1
5.4M
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
330
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
710
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
730
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
780
Transcript
+85৬'MBTL 1Z+85۽ੋૐ"1*ࢲߡٜ݅ӝ 1:$0/,PSFBౚషܻ ӣળഐ
$POUFOUT ܻоѦ৵ೞחо ੋૐੋооߺѱಝࠁӝ ੋૐߑधрױೞѱಝࠁӝ +85ۆ
1ZUIPOীࢲ+85ܳࢎਊೞחੋૐ"1*ࢲߡٜ݅ӝ "EWBODFE5PQJDT Ҋਵәઁٜ
য়טౚషܻীࢲܖחѪܖঋחѪ য়טౚషܻীࢲחղਊਸಝࠅѪੑפ рױೠੋૐੋоJOUSPEVDUJPO 'MBTL৬1Z+85ܳࢎਊೠੋૐ"1*ࢲߡ য়טౚషܻীࢲחղਊನೣೞҊঋणפ
ੋૐੋоܳ৵೧ঠೞաਃ 3#"$ 1ZUIPOEFDPSBUPSܳҳഅೞחߑߨ 'MBTLXFCBQQEFTJHOQBUUFSO
ܻоѦ৵ೞחо .PUJWBUJPO
కୡীחইפҊਢࢲ࠺झח ࢲ࠺झ೧ঠೞחݽٚӝמਸױੌࢲߡীয֍Ҋ .POPSJUIJD ࢲ࠺झܳઁ ҕೞחഋకणפ 8FC 8"4
%# +41 5PNDBU 4FSWMFU .Z4RM ױੌࢲߡীࣁ࣌ࠁী֍ਵݶҊೡѪহભ 6TFS 8FC 8"4 %# GET / index.html (or jsp) ਃ (ਃೞݶ) DB query Querying Data DB ޚ index ಕ (ࢂ) index ಕ
दрաݶࢲ 'SPOUFOEӝࣿبߊೞҊৈ۞оࢲ࠺झҳࢿইఃఫبਊغणפ tۿоঌইࢲ۪؊݂ೞҊߔূ٘ীਃೡԋߔূ٘חؘఠ݅۴u tߔূ٘חۿоਗೞחࢲ࠺झܳೞח"1*݅ઁҕೞݶغѷu ױఋ۽֗য়פ ࢚కਬܳೞঋח3&45ࢲ࠺झૐо
पदр۪؊݂দ 6TFS 8FC "1*4FSWFS %# GET / Index ಕ ௪݂௪݂௪݂.. Querying Data Index.html (৮ࢿغח ࢂ) index ಕ Resource list Resource list
ӏݽоழݶࢲ ഒѢೞӝחޖܻפӬդ"ࢲ࠺झ݅ઁҕೡѱցח#ࢲ࠺झ݅ઁҕ ೞ ࢲ࠺झױਤ۽ࢲߡࣁ࠙ച झாੌইਓ "1*4FSWFS "1*4FSWFS "1*4FSWFS
%# पदр۪؊݂দ 6TFS 8FC GET / (৮ࢿغח ࢂ) index ಕ ࣻ ݆ request
3FRVFTUоפѪջग 4UBUFMFTTೠ3&45ীࢲTUBUFܳਬ೧ঠೞח࢚ടߊࢤ ޛ֤ࠗ࠙3&45"1*חೞաSFRVFTU۽ܻܳղঠೞחѪજणפ ղࠗDPOUSPMMFSীࢲٮ۽۽ਸجܻחೠ؊ۄب Ӓؘ۠QSPUFDUFESFTPVSDFח
ࠁഐ೧ঠೞחਗFH ౠࢎਊоࢎਊೠ SFTPVSDFࠁоઉয়ӝ١ ߐڰ ۞۰ݶݒߣੋૐࢲߡীMPHJOೞҊਃܻೞҊ೧ঠೣ 6TFS 8FC "1*4FSWFS "1*4FSWFS GET / (۽Ӓੋ റ) resource A ࣁਃ resource A resource B ࣁਃ ־ҳջ ք Context ҕਬ X
ੋૐੋооߺѱಝࠁӝ
ੋૐҗੋоҳࢿ ࢎਊ ࢎਊੋૐࠁ *%18 ࢲ࠺झઁҕࢲߡ
पઁܻоઁҕೞҊरࢲ࠺झ ੋૐ߂ࢎਊೲо ੋо ػࢎਊ݅ࢎਊоמ ੋૐੋоࢲߡ ࢎਊੋૐਸ ੋૐػࢎਊࢲ࠺झࢎਊӂೠҙܻ
ੋૐ ੋૐ "VUIFOUJDBUJPO ࢚ࢲ࠺झ PSࢲߡ ীղо־ҳੋܳഛੋ߉חੌ
ࠁా ੋૐਸೞӝਤೠࠁܳCPEZ۽ࠗೞৈਃ *%18 UPLFO ੋૐػTFTTJPO١ ੋૐࢲߡ 6TFS tղо#PCਃu ੋૐ tইפঠu ੋૐѾҗࢲ࠺झী١۾ػࢎਊ١۾غঋࢎਊ ੋૐ%# tੴ#PC u t֨u
ੋо ੋо "VUIPSJ[BUJPO ղоস SFTPVSDF ਸࣻ೯ೡӂೠ "VUIPSJUZ
оҊഛੋ߉חੌ ੋоܳਃೞחࢎਊחੋૐغযযঠೣ ࠁాౠ೯ਤ BDUJPO ীೞৈӂೠ USVF হ GBMTF ܳ߈ജ ੋоࢲߡ ࠁాੋૐࢲߡ৬э ࢲ࠺झઁҕࢲߡ 6TFS tա#PCੋؘ 7.ೞա݅ۄu ࢲ࠺झਃ t#PC7.ٜ݅ӂೠযਃ u ੋоӂೠ ঠॳ USVF ৈӝ7. ࢲ࠺झѾҗ
ੋૐߑधрױೞѱಝࠁӝ
4FTTJPOӝ߈ੋૐੋоߑध ాੋߑध $MJFOUDPPLJFীੋૐੋоࠁܳ֍ঋ FH DPPLJF<rJT@MPHJOs> TFTTJPOLFZчਸਬೞৈ
ࢲߡীࢲਃೠTFTTJPOEJDUী۽Ӓੋਬޖ 5SVF'BMTF ܳঌইࠁחߑध ݒрױ &OUFSQSJTFࢲߡীࢲחࣁ࣌ਸҕਬೞחӝࣿਃ 4FTTJPODMVTUFSJOH PWFSIFBE $PPLJFܳੜTBMU೧ࢲঐഐച WVMOFSBCJMJUZ from flask import Flask, request, session app = Flask(__name__) @app.route('/is_login,', methods=['POST']) def is_login(): return session['logged_in'] # True / False
ੌ߈ੋ 5PLFOӝ߈ੋૐੋоߑध 4FTTJPOীҳগ߉ঋҊ SFRVFTUীੋૐੋоҙ۲ࠁܳೣԋࠁղܻ ੌ߈ਵ۽IUUQSFRVFTUIFBEFSীUPLFOࠁܳನೣೞৈ࣠ ۽ӒੋBDDFTT@UPLFOߊә
0"VUICFBSFS 0"VUI0QFO*% +85١ ੋૐࢲߡ 6TFS *%#PC 18#PC#PC#PC షߊәਃ షߊә BDDFTT@UPLFOOBXLEKOBLKTDOLj ࢲ࠺झઁҕࢲߡ ࢲ࠺झਃ IFBEFSBDDFTT@UPLFOOBXLj 63*(&5TFSWJDF
৵0"VUIউॄਃ ࢶѐ֛ӝ 0"VUIח3'$ীػੋૐੋоQSPUPDPMTUBOEBSE 3'$ য়טܻоࢎਊೞҊೞח+85חੋૐীࢎਊೞחUPLFOGPSNBU
ৈ۞࠙ࢤпೞח0"VUI ,ࢎ۽Ӓੋ0"VUI (ࢎ۽Ӓੋ0"VUI 'ࢎ 0"VUI חݽف0"VUIQSPUPDPMਸ݅दఃח*NQMFNFOUBUJPO ܻоঌҊח0"VUI0QFO*%ੑפ 0QFO*%ߑध৻ࠗܳ֗য়ӝٸޙীղࠗݎઁೠ١ۄࡁࢲ࠺झী חࠗ
ѱо SFRVFTUоUPLFOਸٜҊ৳Ҋ೧ࢲޖࢲ࠺झܳઁҕೡࣻহणפ UPLFOSBOEPN@HFOFSBUFE@TUSJOH UPLFO೧ӏਵ۽ߊәೠѪੋഛੋ %#.4 PUIFS"1* ਃ
UPLFOࢲ࠺झप೯ӂೠоҊחبഛੋਃ
+85ۆ
+40/8FC5PLFO ӝઓহחBDDFTTUPLFOীܳࠗৈ೧ࠁ 5PLFOഛੋױ҅ ੋо ܳੋૐࢲߡীޚঋҊ"1*ࢲߡࣻળীࢲ೧Ѿೞ ޚبٮب݈Ҋযڌѱࢤѹݡחо
ѐQBSU IFBEFS QBZMPBE WFSJGZTJHOBUVSF EPU ਵ۽ҳ࠙ - header.payload.signature eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. (ࢎਊೠ algorithm, token type: JWT) eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. (ੋૐ ࠁ SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c (Ѩૐਸ ਤೠ Signature)
+85JOEFUBJM - Header ೧UPLFOࢎਊೞחBMHPSJUIN 5PLFO5ZQF - Payload
UPLFOӂೠࠁ ੋૐࠁ ࢎਊࠁ TDPQF ݅ܐӝр - Signature ਤ߸ઑѨਸਤೠTJHOBUVSF
1BZMPBEJOEFUBJM Payloadীನೣغחղਊٜ JO3'$ SFTFSWFEGJFME iss (issuer)UPLFOߊ೯ sub
(subject)ࢎਊ৬ࢎਊSFTPVSDF63*ઁݾ aud (audience)ߊә࢚ exp (expiration date)ష݅ܐغחदр nbf (not before)షഝࢿചदр чറࠗఠషഝࢿച iat (issued at)షߊәदр jti (JWT ID)5PLFOҳ߹ਸਤೠVOJRVF*% scopeUPLFOࢎਊHSBOUػӂೠ QSJWBUFGJFME ݽٚ Payload Fieldܳ ࢎਊೡ ਃח হ!
+85ܳࢎਊೠੋૐର Client Server (ੋૐ + API) 1045 MPHJOFOEQPJOU XJUI*% 18
"1*4FSWFS SFEJSFDU ੋૐࢲߡ ੋૐറ+85షߊә +85షਸ#SPXTFSীੜ ఃPSTFTTJPO 4FSWJDFSFRVFTUXJUI+85UPLFOJO"VUIPSJ[BUJPO)FBEFS +85TJHOBUVSFѨૐ ਃೠ҃ +85ীࢲ "VUIPSJUZѨૐറࢲ࠺झઁҕ 1SPUFDUFE3FTPVSDF4FSWJDFSFTQPOTF
8IZ+85 ׳߉UPLFOীೞৈੋૐࢲߡী೧UPLFOWBMJEJUZৈࠗܳޛযࠅਃ оহ ޖ۰JOEVTUSZTUBOEBSE 3'$ 5PLFOӝ߈ੋૐߑधীࢲUPLFOGPSNBUਵ۽ੋ߉
ޙઁب݅ٯ উ ইפѢUPLFOఎஂظࢲڙэUPLFOਵ۽SFRVFTUզܻݶޙઁغחѪইצ оਃ эషীೞৈэࢎۈੋधэ*%18۽эࢎۈੋधҗэޙ ઁ +85ࠁউࢿҗחܲোѾా۽ޙઁ
1ZUIPOীࢲ+85ܳࢎਊೞחੋૐ"1*ࢲߡٜ݅ӝ
3FRVJSFEQBDLBHFT য়טࢎਊೡౚషܻীࢲࢎਊೡಁఃݾ۾ 1Z+85 'MBTL 3FRVFTUT
QJQJOTUBMM1Z+85'MBTLSFRVFTUT
BVUI@TFSWFSQZ from flask import Flask, jsonify import jwt import datetime
app = Flask(__name__) secret_key = ‘secret_key' # This should be handled by configuration DB or third-party tool @app.route('/') def index(): return "Hello auth server” # Test for server is working @app.route("/get_token") def get_token(): # db স ਃפ. (ౚషܻীࢲח ࢤۚפ.) issuer = 'pycon_tutorial' subject = ‘localhost:5000/v1' date_time_obj = datetime.datetime exp_time = date_time_obj.timestamp(date_time_obj.utcnow() + datetime.timedelta(hours=24)) scope = ['v1', 'v2'] payload = { 'sub': subject, 'iss': issuer, 'exp': int(exp_time), 'scope': scope } token = jwt.encode(payload, secret_key, algorithm='HS256') return jsonify({ 'msg': 'token is generated', 'access_token': str(token) }), 201
BVUI@TFSWFSQZ ҅ࣘ @app.route("/admin_login") def admin_login(): issuer = ‘pycon_tutorial' # scope
ܲ login যڌѱ ܻೡө? subject = 'localhost:5000/v1' date_time_obj = datetime.datetime exp_time = date_time_obj.timestamp(date_time_obj.utcnow() + datetime.timedelta(hours=24)) scope = ['v1', 'v2', 'v3'] payload = { 'sub': subject, 'iss': issuer, 'exp': int(exp_time), 'scope': scope } token = jwt.encode(payload, secret_key, algorithm='HS256') return jsonify({ 'msg': 'token is generated', 'access_token': str(token) }), 201 app.run(port=5001)
TFSWJDF@TFSWFSQZ from flask import Flask, jsonify, abort, request import jwt
import requests from functools import wraps app = Flask(__name__) secret_key = 'secret_key' # third-party ో۽ ҙܻغযঠ פ. def jwt_token_required(f): # flask-jwt-extendedীب ઁҕೞח Ѫۢ ؘۨఠ ୶оೞӝ / customizing оמೞب۾ self ҳഅ @wraps(f) def decorated_function(*args, **kwargs): # header ରח # token ࢚ੋѤ if not 'Authorization' in request.headers: return jsonify({ 'msg': 'token is not given' }), 400 token = request.headers['Authorization'] try: decoded_token = jwt.decode(token, secret_key, algorithms=['HS256']) except: return jsonify({ 'msg': 'Invalid token given' }), 400 kwargs['decoded_token'] = decoded_token return f(*args, **kwargs) return decorated_function @app.route('/') def index(): return "Hello Pycon Server"
TFSWJDF@TFSWFSQZ ҅ࣘ @app.route('/login') def login(): r = requests.get(“http://127.0.0.1:5001/get_token") # login
auth-serverী షਸ ߊә߉ח ೯ਤ rsp_json = r.json() token = rsp_json['access_token'] return jsonify({ 'access_token': token, 'msg': "Successfully login" }), 200 @app.route("/protected_service") @jwt_token_required def protected_service(**kwargs): return jsonify({ 'msg': 'hello protected user' }), 200 @app.route("/v3") @jwt_token_required def other_scope_service(**kwargs): token = kwargs['decoded_token'] if 'v3' in token[‘scope']: # ୶о۽ ӂೠ ഛੋ ೞח স / decoratorܳ ࣻೞৈ ࠗ࠙ਸ ઁѢೡ ࣻب णפ. # service logic return jsonify({ 'msg': 'welcome v3 user' }), 200 else: return jsonify({ 'msg': 'You are not authorized' }), 401 app.run()
"EWBODFE5PQJDT
5PLFOਸউೞѱࢎਊೞחߑߨ 5PLFO߈٘द)UUQ0OMZDPPLJFীפ 944ҕѺߑ ఃܳࢎਊೞৈ+85ܳೠݶ $43'ীೠߑযܳ೧ঠפ ܻоݽܰחࢎীܲبݫੋীࢲਃৢࣻ
4FDSFULFZחੋૐ"1*ࢲߡ ࢲ࠺झ"1*ࢲߡ݅оҊযঠפ ݒߣషਸࠁউః۽Ѩૐ೧ࢲৢ߄ܲఃੋѨૐ೧ঠೣ ъ۱ೠఃߑध DMJFOUীח֢غঋইঠೣ хೠؘఠחQBZMPBEী֍ঋইঠפ 3FQMBZҕѺਸߑೞӝਤ೧ࢲחUPLFOਬബदрਸૣѱפ 3VMFPGUIVNCחઓೞঋઁҕೞחࢲ࠺झীٮۄࢲ
3FGSFTI5PLFO ߊәೠUPLFOਸୌ֙݅֙ࢎਊೡࣻחহणפ ੌӝрդUPLFOߊәਸ೧ঠפ ࢲ࠺झܳਃೞоࢎਊೞ؍UPLFOӝр݅ܐػ҃ SFGSFTI@UPLFOਸ ٜҊషߊәਃਸ೧ঠפ
5PLFOࠁҙߑߨࢎਊഋకীٮۄࢲ access_tokenTFSWJDF"1*ࢲߡࣻળীࢲ TFDSFULFZEFDPEFܳా೧ ࢲ ܻоמೞ݅ SFGSFTI@UPLFO߈٘दBVUIࢲߡܳా೧ࢲೠߣ؊Ѩૐ ਃפ ࢎਊоמೠUPLFOߊә۽ ECBDDFTTਃ
TFDSFU@LFZܳ߸҃ೞҊरযਃ ࢎप ઁח+85৬ҙ۲ݢઁ ࢜۽TFDSFU@LFZߊә+85৬ҙ۲হחօਸా೧ࢲߊәೞחѪݏ णפ о۸UIJSEQBSUZܳՙҊٜযоঠೠ؍о
FH )5514 PS44- DPOGJH@TFSWFSীࢲQVCTVCҳઑ۽ਊоמ
$MBJN֢JTTVF +85חױࣽIFBEFS DMBJN TJHOBUVSFܳCBTFFODPEJOHೠTUSJOH TJHOBUVSFחTFDSFULFZоನೣػTBMUFETUSJOHۄఎஂغযبղਊ߸ઑ غݶޙઁ9 DMBJNࢎਊੋૐࠁоӒ۽֢ؼ۰о
VTFSFNBJM١ӝఋࢎਊѐੋࠁо֢ؼ۰ оמೠ+85ীࠛਃೠࠁܳѱইঠפ FNBJMэ ߈ب QVCMJDೠࠁח֢غחࣽрܻTFSWJDFחইפ؊ ۄبܲ۽ޙઁоࢤӡࣻب ژחܲMBZFSب )5514 DMBJNਸ୶оঐഐചبхೠࢲ࠺झীࢲח Ҋ۰оמ
хࢎפ
"QQFOEJY"0"VUI'MPX From http://www.sauru.so/blog/basic-of-oauth2-and-jwt/
"QQFOEJY#0"VUI'MPX From http://earlybird.kr/1584