Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

ొஃऀ঺հ ࢘ձ

Slide 3

Slide 3 text

ຊ೔ͷྲྀΕ Φʔϓχϯά r FTUJFͱ͸ʁ <NJO> LFOLPPPP ʰ3VTUͰ΢ΣϒΞϓϦʱ<NJONJO2"> ฏా౦ເʰ3VTUº/FYUKTº"VUIͰϢʔβʔೝূʱ<NJONJO2"> શମΛ௨ͯ͠ͷ࣭ٙɾΫϩʔδϯά <NJO> )BTIUBHFTUJF@ST 2"ػೳΛͥͻ͝׆༻͍ͩ͘͞ʂ

Slide 4

Slide 4 text

FTUJFͱ͸ʁ

Slide 5

Slide 5 text

Slide 6

Slide 6 text

৽ίʔϙϨʔταΠτ ʢ IUUQTXXXFTUJFKQDPSQ ʣ ͷ͝঺հ

Slide 7

Slide 7 text

͜Ε·ͰͷϓϩμΫτ܈

Slide 8

Slide 8 text

ͦΕΛࢧ͑ΔਐԽ͠ଓ͚ΔσʔλύΠϓϥΠϯ

Slide 9

Slide 9 text

20/4 20/5 20/6 20/7 20/8 20/9 20/10 20/11 20/12 21/1 21/2 21/3 21/4 21/5 21/6 21/7 21/8 21/9 21/10 21/11 ϏδωεΠϯύΫτ ओͳಋೖاۀ ԻॱɺҰ෦ൈਮ BOENPSF .33 Y ௚ۙϲ݄

Slide 10

Slide 10 text

1IBTF ۭࣨɾاۀ৘ใͷ σʔλج൫ߏங 1IBTF 1IBTF τϥϯβΫγϣϯ ϓϥοτϑΥʔϜ

Slide 11

Slide 11 text

ෳ਺ϓϩμΫτͷ૬৐ޮՌͰاۀՁ஋ΛരൃతʹߴΊΔ 1SPEVDU ۭࣨɾاۀ৘ใͷ σʔλج൫ߏங 1SPEVDU 1SPEVDU τϥϯβΫγϣϯ ϓϥοτϑΥʔϜ "1*ߏ૝ ଟ༷ͳݴޠ ৽͍͠ϓϩμΫτͷ͕ͭόοΫΤϯυΛ3VTUͰॻ͍ͯ·͢ʂ ʢࢣఋ੍౓Λ੔͑࢝Ί͍ͯ·͢ʣ

Slide 12

Slide 12 text

ͬͦ͘͞-5͍͖·͠ΐ͏ʂ

Slide 13

Slide 13 text

3VTUͰ΢ΣϒΞϓϦ ΞϧόΠτʢਂ໷ɾٳ೔γϑτʣ LFOLPPPP

Slide 14

Slide 14 text

3VTUͱ͸

Slide 15

Slide 15 text

3VTUͷಛ௕ $ฒʹ଎͍ ΋ͱ΋ͱ'JSFGPY༻ݴޠ -JOVYΧʔωϧʹ࢖ΘΕͦ͏ "84Ͱ͸7.΍04ͳͲʹ࢖ΘΕ͍ͯΔ ίϯύΠϥ͕Ϧιʔε؅ཧʹ͍ͭͯνΣοΫ͠·͘Δ

Slide 16

Slide 16 text

Ͱ΋ɺ೉͍͠ΜͰ͠ΐ͏ʜʁ

Slide 17

Slide 17 text

3VTU͕೉͍͠ͱ͍͏ӟ ίϯύΠϥͷνΣοΫ͕ݫ͗ͯ͢͠Ұੜ௨Βͳ͍ʜ ॴ༗ݖʁ஌Βͳ͍֓೦͕ͨ͘͞Μग़ͯ͘Δʜ

Slide 18

Slide 18 text

ͦ΋ͦ΋ϓϩάϥϛϯά͕೉͍͠ʂʂʂ

Slide 19

Slide 19 text

void listOperation(List list) { list.add("Awesome!"); } Javaではよく⾒る関数だが…

Slide 20

Slide 20 text

void listOperation(List list) { list.add("Awesome!"); } Javaではよく⾒る関数だが… • 実は List がミュータブルであることを強制 • ImmutableList を渡すと Runtime Exception • 呼び出し元でも予期しないかも?

Slide 21

Slide 21 text

void listOperation(List list) { list.add("Awesome!"); } Javaではよく⾒る関数だが… • 実は List がミュータブルであることを強制 • ImmutableList を渡すと Runtime Exception • 呼び出し元でも予期しないかも? →コメントをつける・関数名を⼯夫するしかない

Slide 22

Slide 22 text

fn list_operation(list: Vec) {…} • 呼び出し元では list は使われない • move しているので fn list_operation(list: &Vec) {…} • イミュータブルな参照 fn list_operation(list: &mut Vec) {…} • ミュータブルな参照

Slide 23

Slide 23 text

ϓϩάϥϛϯά͸೉͍͠ʜ ͦ΋ͦ΋ϓϩάϥϛϯά͸೉͍͠ʜ ϓϩάϥϛϯάͷ೉͍͠ϙΠϯτΛਓྗͰνΣοΫ͢Δͷ͸େมʜ ฒྻϓϩάϥϛϯά͸ਓྨʹ͸ෆՄೳ 3VTUʹ೉͍͠ϙΠϯτΛԡ͚ͭ͠Α͏ʂ

Slide 24

Slide 24 text

-JOVY࡞Βͳ͍ͷͰʜ

Slide 25

Slide 25 text

3VTU͸௿ϨΠϠʔઐ༻ݴޠͰ͸ͳ͍ʂ ศརͳݴޠػೳ͕͋Δ ݸਓతͳΠνΦγ͸ USBJU $BSHPͱ͍͏ඪ४ͷύοέʔδ؅ཧπʔϧ͕͋Δ ීஈͷϓϩάϥϛϯάݴޠͱͯ͠Φεεϝ

Slide 26

Slide 26 text

3VTUͰ΢Σϒ։ൃ

Slide 27

Slide 27 text

3VTUΛऔΓר͘΢Σϒ։ൃࣄ৘ ೥൒લʹඇಉظߏจ BTZODBXBJU͕҆ఆԽ ͦΕҎલ΋ඇಉظॲཧ͸ग़དྷ͕ͨɺ؆୯ʹॻ͚ΔΑ͏ʹͳͬͨ ೥͔͚ͯϥΠϒϥϦɾϑϨʔϜϫʔΫ͕ॆ࣮ ݹࢀϥΠϒϥϦ͕ BTZODBXBJUରԠ ॻ͖΍͔͢͞Β৽͍͠ϥΠϒϥϦ΋ଓʑ

Slide 28

Slide 28 text

3VTUͰ΢ΣϒΞϓϦ • ΢ΣϒϑϨʔϜϫʔΫBDUJYXFC • +BWBͷ 4QSJOHɺ1ZUIPOͷ 'MBTL • 42-υϥΠόʔTRMY • .Z42-Ͱ࢖༻ • 03.Ͱ͸ͳ͘ɺΫΤϦ௚ॻ͖ • 4ΫϥΠΞϯτSVTPUP • ݹࢀ "84ϥΠϒϥϦ

Slide 29

Slide 29 text

#[post("/api/buildings")] pub async fn create_building( request: Json, pool: Data, auth0_id: ReqData, ) -> Result { let building = Building::from(request.building); verify_user(&pool, &auth0_id.0).await?; let id = Building::insert(&pool, &building).await?; Ok(Json(CreateBuildingResponse { building_id: id })) }

Slide 30

Slide 30 text

#[post("/api/buildings")] pub async fn create_building( request: Json, pool: Data, auth0_id: ReqData, ) -> Result { let building = Building::from(request.building); verify_user(&pool, &auth0_id.0).await?; let id = Building::insert(&pool, &building).await?; Ok(Json(CreateBuildingResponse { building_id: id })) } JSONとして受け取るように指定 FWでパース等やってもらう

Slide 31

Slide 31 text

#[post("/api/buildings")] pub async fn create_building( request: Json, pool: Data, auth0_id: ReqData, ) -> Result { let building = Building::from(request.building); verify_user(&pool, &auth0_id.0).await?; let id = Building::insert(&pool, &building).await?; Ok(Json(CreateBuildingResponse { building_id: id })) } FWからSQLコネクションプールを もらってくる

Slide 32

Slide 32 text

#[post("/api/buildings")] pub async fn create_building( request: Json, pool: Data, auth0_id: ReqData, ) -> Result { let building = Building::from(request.building); verify_user(&pool, &auth0_id.0).await?; let id = Building::insert(&pool, &building).await?; Ok(Json(CreateBuildingResponse { building_id: id })) } ヘッダからトークンを取り出して IDを取得しておいてもらう

Slide 33

Slide 33 text

#[post("/api/buildings")] pub async fn create_building( request: Json, pool: Data, auth0_id: ReqData, ) -> Result { let building = Building::from(request.building); verify_user(&pool, &auth0_id.0).await?; let id = Building::insert(&pool, &building).await?; Ok(Json(CreateBuildingResponse { building_id: id })) } 返り値は Result

Slide 34

Slide 34 text

#[post("/api/buildings")] pub async fn create_building( request: Json, pool: Data, auth0_id: ReqData, ) -> Result { let building = Building::from(request.building); verify_user(&pool, &auth0_id.0).await?; let id = Building::insert(&pool, &building).await?; Ok(Json(CreateBuildingResponse { building_id: id })) }

Slide 35

Slide 35 text

Slide 36

Slide 36 text

let id = Building::insert(&pool, &building).await?;

Slide 37

Slide 37 text

let id = Building::insert(&pool, &building).await?;

Slide 38

Slide 38 text

3VTUʹ͓͚Δ 3FTVMUܕͷ FBSMZSFUVSO value, err := f() if err != nil { return nil, err } let value = f()?;

Slide 39

Slide 39 text

#[post("/api/buildings")] pub async fn create_building( request: Json, pool: Data, auth0_id: ReqData, ) -> Result { let building = Building::from(request.building); verify_user(&pool, &auth0_id.0).await?; let id = Building::insert(&pool, &building).await?; Ok(Json(CreateBuildingResponse { building_id: id })) } マクロで⾊々⽣成してもらう

Slide 40

Slide 40 text

BDUJYXFC·ͱΊ • ΄͔ͷݴޠͱಉ͘͡Βָ͍ʹ "1*͕ॻ͚Δ • ඇಉظॲཧ͸ BTZODBXBJU • ΤϥʔϋϯυϦϯά͸ 3FTVMUͱ

Slide 41

Slide 41 text

TRMYͱ 3VTUϚΫϩ

Slide 42

Slide 42 text

3VTUͷ42-؀ڥ • %JFTFMͱ͍͏ݹࢀ03. • ඇಉظɺඇରԠʜ • ඇಉظରԠͷ 42-ϥΠϒϥϦ TRMY • ΫΤϦ௚ॻ͖ • ڧྗͳϚΫϩ

Slide 43

Slide 43 text

async fn insert(pool: &MySqlPool, unit: &Unit) -> Result { let unit_id = sqlx::query(r#" INSERT INTO units ( area, floor, building_id ) VALUES (?,?,?)"#, ) .bind(unit.area) .bind(unit.floor) .bind(unit.building_id) .execute(pool) .await? .last_insert_id(); Ok(unit_id) }

Slide 44

Slide 44 text

async fn find_by_bid(pool: &MySqlPool, bid: i64) -> Result> { let units = sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid ) .fetch_all(pool) .await?; Ok(units) }

Slide 45

Slide 45 text

async fn find_by_bid(pool: &MySqlPool, bid: i64) -> Result> { let units = sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid ) .fetch_all(pool) .await?; Ok(units) }

Slide 46

Slide 46 text

sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid )

Slide 47

Slide 47 text

sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid )

Slide 48

Slide 48 text

sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid ) struct RawUnit { unit_id: i64, area: Decimal, floor: u8, building_id: i64, }

Slide 49

Slide 49 text

sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid ) struct RawUnit { unit_id: i64, area: Decimal, floor: u8, building_id: i64, } もし NULL が含まれていたら……?

Slide 50

Slide 50 text

sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid ) struct RawUnit { unit_id: i64, area: Decimal, floor: u8, building_id: i64, } ↑ このクエリの返り値の型が RawUnit と同じか、 コンパイル時にチェックする。

Slide 51

Slide 51 text

42-ΫΤϦͷฦΓ஋ͷܕΛ ίϯύΠϧ࣌ʹνΣοΫ͢Δʙʂʁʂʁ

Slide 52

Slide 52 text

3VTUϚΫϩͷେ·͔ͳಈ͖ τʔΫϯྻΛड͚औΔ ͍Ζ͍Ζॲཧ͢Δ ͜ͷ෦෼΋3VTUͰॻ͚Δ ίʔυΛੜ੒͢Δ

Slide 53

Slide 53 text

sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid )

Slide 54

Slide 54 text

sqlx::query_as!( RawUnit, "SELECT * FROM units WHERE building_id=?", bid ) トークン列

Slide 55

Slide 55 text

3VTUϚΫϩͷେ·͔ͳಈ͖ τʔΫϯྻΛड͚औΔ ͍Ζ͍Ζॲཧ͢Δ ͜ͷ෦෼΋3VTUͰॻ͚Δ ίʔυΛੜ੒͢Δ

Slide 56

Slide 56 text

3VTUϚΫϩͷେ·͔ͳಈ͖ τʔΫϯྻΛड͚औΔ ͍Ζ͍Ζॲཧ͢Δ ͜ͷ෦෼΋3VTUͰॻ͚Δˠ42-ʹ઀ଓͯ͠ɺΫΤϦͷܕΛ֬ೝ ίʔυΛੜ੒͢Δ

Slide 57

Slide 57 text

⼈類 コンパイラ MySQL コード クエリ 型 型チェッ ク

Slide 58

Slide 58 text

·ͱΊɿίϯύΠϧ࣌42-ܕνΣοΫ

Slide 59

Slide 59 text

શମͷ·ͱΊ 3VTU͸೉͍͠ʁ ˠ ϓϩάϥϛϯά͕೉͍͠ʂ 3VTU͸௿ϨΠϠʔ޲͚ʁ ˠ ΢Σϒ։ൃ͠Α͏ʂ ϚΫϩ͍͢͝ʁ ˠ ͍͢͝Αʜ

Slide 60

Slide 60 text

3VTUº/FYUKTº"VUIͰϢʔβʔೝূ 48& 5PNV )JSBUB !UPNV@EFTVZP

Slide 61

Slide 61 text

എܠ "VUIº/FYUKT "VUIº"DUJY@XFC "HFOEB

Slide 62

Slide 62 text

• estieはマルチプロダクト化を進めている • それぞれのサービスは将来統合していく想定がある • その際ユーザー情報も統⼀的に管理しきたい എܠ

Slide 63

Slide 63 text

個々のサービスそれぞれで認証機能を作りたくはない 全社的な認証基盤を作り始める前にIDaaSの技術検証を進めたい 新規プロダクトでAuth0認証を使うことに എܠ

Slide 64

Slide 64 text

ϓϩμΫτͷߏ੒ Backend ID Provider BFF Frontend

Slide 65

Slide 65 text

ೝূϑϩʔ Backend ID Provider BFF Frontend ID Token ID & Password セッションCookie JWK ID Token トークンを検証 レスポンス

Slide 66

Slide 66 text

എܠ "VUIº/FYUKT "VUIº"DUJY@XFC "HFOEB

Slide 67

Slide 67 text

• クライアント側で認証情報を保持したい • トークンの偽装を難しくしたい ୡ੒͍ͨ͜͠ͱ

Slide 68

Slide 68 text

ϑϩϯτΤϯυ͔ΒͷϩάΠϯ Backend ID Provider BFF Frontend ID Token ID & Password

Slide 69

Slide 69 text

ϑϩϯτΤϯυ͔ΒͷϩάΠϯ Backend ID Provider BFF Frontend ID Token ID & Password セッションCookie

Slide 70

Slide 70 text

ϑϩϯτΤϯυ͔ΒͷϩάΠϯ Backend ID Provider BFF Frontend ID Token ID & Password セッションCookie トークンはサーバーサイド で暗号化・復号化

Slide 71

Slide 71 text

*%τʔΫϯΠϯ ペイロード部分の例 +855PLFOͷߏ଄ • ϔομʔ෦ • ॺ໊ݕূ৘ใΛؚΉ • ϖΠϩʔυ෦ • ΞΧ΢ϯτͷଐੑ৘ใͳͲΛؚΉ • ॺ໊෦ • ೝূࡁΈͰ͋Δ͜ͱΛݕূ͢Δॺ໊ΛؚΉ

Slide 72

Slide 72 text

/FYUKTº"VUIΠϯ "VUI3FBDUKT 4%, IUUQTHJUIVCDPNBVUIBVUISFBDU • /FYUKTͰ4UBUJD)5.-&YQPSUΛ࢖༻͍ͯ͠Δ৔߹ • αʔόʔαΠυϨϯμϦϯά࣌ʹϢʔβʔσʔλʹΞΫηε͢Δඞཁ͕ͳ͍৔߹ • /FYUKTͷ"1*3PVUFTΛϓϩΩγͱͯ͠࢖༻ͯ͠֎෦"1*Λݺͼग़͢ͷͰ͸ͳ͘ɺΞΫηε τʔΫϯΛऔಘͯ͠ϑϩϯτΤϯυϨΠϠʔ͔Β௚઀֎෦"1*Λݺͼग़͍ͨ͠৔߹ "VUI/FYUKT 4%, IUUQTHJUIVCDPNBVUIOFYUKTBVUI • ͦΕҎ֎ͷ৔߹ • $PPLJFͰͷηογϣϯͷ؅ཧ͕Մೳ

Slide 73

Slide 73 text

എܠ "VUIº/FYUKT "VUIº"DUJY@XFC "HFOEB

Slide 74

Slide 74 text

• リクエストしてきているユーザーの認証を⾏いたい • リクエストに付属したトークンの検証を⾏いたい ୡ੒͍ͨ͜͠ͱ

Slide 75

Slide 75 text

ϑϩϯτΤϯυ͔ΒͷϩάΠϯ Backend ID Provider BFF Frontend ID Token

Slide 76

Slide 76 text

ϑϩϯτΤϯυ͔ΒͷϩάΠϯ Backend ID Provider BFF Frontend JWKを要求 ID Token

Slide 77

Slide 77 text

ϑϩϯτΤϯυ͔ΒͷϩάΠϯ Backend ID Provider BFF Frontend JWK JWKを要求 ID Token

Slide 78

Slide 78 text

ϑϩϯτΤϯυ͔ΒͷϩάΠϯ Backend ID Provider BFF Frontend JWK JWTの検証 JWKを要求 ID Token

Slide 79

Slide 79 text

ϑϩϯτΤϯυ͔ΒͷϩάΠϯ Backend ID Provider BFF Frontend JWK ID Token JWTの検証 レスポンス JWKを要求

Slide 80

Slide 80 text

όοΫΤϯυͰͷϢʔβʔͷೝূΠϯ "DUJY@XFCͷϛυϧ΢ΣΞͰ*%5PLFOΛݕূ͢Δ • "VUIPSJ[BUJPOϔομʔ͔Β+85τʔΫϯΛ֫ಘ • "VUIʹݕূ༻ͷ+8,ΛϦΫΤετ • τʔΫϯΛݕূ

Slide 81

Slide 81 text

όοΫΤϯυͰͷϢʔβʔͷೝূ pub struct Auth0Middleware { service: Rc, client: Rc, } impl Auth0Middleware { fn call(&self, req: ServiceRequest) -> Self::Future { let token = parse_bearer_token(&req)?; let auth0_id = match client.get_auth0_id_from_bearer(token); req.extensions_mut().insert(auth0_id); service.call(req).await.map(|res| res.map_into_left_body()) } }

Slide 82

Slide 82 text

όοΫΤϯυͰͷϢʔβʔͷೝূ pub struct Auth0Middleware { service: Rc, client: Rc, } impl Auth0Middleware { fn call(&self, req: ServiceRequest) -> Self::Future { let token = parse_bearer_token(&req)?; let auth0_id = match client.get_auth0_id_from_bearer(token); req.extensions_mut().insert(auth0_id); service.call(req).await.map(|res| res.map_into_left_body()) } } HTTPの Authorization HeaderからJWT トークンを抽出

Slide 83

Slide 83 text

όοΫΤϯυͰͷϢʔβʔͷೝূ pub struct Auth0Middleware { service: Rc, client: Rc, } impl Auth0Middleware { fn call(&self, req: ServiceRequest) -> Self::Future { let token = parse_bearer_token(&req)?; let auth0_id = match client.get_auth0_id_from_bearer(token); req.extensions_mut().insert(auth0_id); service.call(req).await.map(|res| res.map_into_left_body()) } } JWTトークンを検証 し、auth0のIDを抽 出する

Slide 84

Slide 84 text

όοΫΤϯυͰͷϢʔβʔͷೝূ fn parse_bearer_token(request: &ServiceRequest) -> Result<&str> { let header = request.headers() .get(&actix_web::http::header::AUTHORIZATION)?; let mut parts = header.to_str()?.splitn(2, ' '); let token = parts[1].ok_or_else(|| anyhow::anyhow!("no token"))?; Ok(token) } • BDUJYXFCͷBQJΛ༻͍ͯ"VUIPSJ[BUJPOϔομʔΛநग़ • ϔομʔͷܗࣜ͸ #FBSFSYYYYYYYYYYYYY

Slide 85

Slide 85 text

όοΫΤϯυͰͷϢʔβʔͷೝূ +85τʔΫϯΛݕূ͢ΔΫϥΠΞϯτ pub struct Auth0Client { client: reqwest::Client, base_url: String, } impl Auth0Client { pub(super) async fn get_auth0_id_from_bearer(&self, bearer_token: &str) -> Result { self.validate_jwt_token(bearer_token).await?.sub //JWT payloadのsub } /////ここに⾊々なメソッド }

Slide 86

Slide 86 text

όοΫΤϯυͰͷϢʔβʔͷೝূ +85τʔΫϯΛݕূ͢ΔҰ࿈ͷॲཧ async fn validate_jwt_token(&self, token: &str) -> Result { let jwks = self.fetch_jwks().await?; let kid = match decode_header(token)?.kid.unwrap(); let jwk = match jwks.find(&kid) { Some(res) => res, None => return Err(anyhow::anyhow!("Specified key not found in set")), }; Auth0Client::dec_jwt(jwk, token) }

Slide 87

Slide 87 text

όοΫΤϯυͰͷϢʔβʔͷೝূ +85τʔΫϯΛݕূ͢ΔҰ࿈ͷॲཧ async fn validate_jwt_token(&self, token: &str) -> Result { let jwks = self.fetch_jwks().await?; let kid = match decode_header(token)?.kid.unwrap(); let jwk = match jwks.find(&kid) { Some(res) => res, None => return Err(anyhow::anyhow!("Specified key not found in set")), }; Auth0Client::dec_jwt(jwk, token) } Auth0に検証⽤の鍵 をリクエスト

Slide 88

Slide 88 text

+85τʔΫϯΛݕূ͢ΔҰ࿈ͷॲཧ async fn validate_jwt_token(&self, token: &str) -> Result { let jwks = self.fetch_jwks().await?; let kid = match decode_header(token)?.kid.unwrap(); let jwk = match jwks.find(&kid) { Some(res) => res, None => return Err(anyhow::anyhow!("Specified key not found in set")), }; Auth0Client::dec_jwt(jwk, token) } 署名部を⽤いて トークンを検証 όοΫΤϯυͰͷϢʔβʔͷೝূ

Slide 89

Slide 89 text

+8,ΛϦΫΤετ͢Δ async fn fetch_jwks(&self) -> Result { let uri = format!("{}/.well-known/jwks.json", self.base_url); let res = self.client.get(uri).send().await?; let val = res.json::().await?; Ok(val) } όοΫΤϯυͰͷϢʔβʔͷೝূ

Slide 90

Slide 90 text

όοΫΤϯυͰͷϢʔβʔͷೝূ +85τʔΫϯΛݕূ͢Δ fn dec_jwt(jwk: &Jwk, jwt: &str) -> Result { match decode::( jwt, &DecodingKey::from_rsa_components(&jwk.n, &jwk.e), &Validation::new(Algorithm::RS256), ) { Ok(c) => Ok(c.claims), e => Err(anyhow::anyhow!("failed to decode jwt: {:?}", e)), } }

Slide 91

Slide 91 text

όοΫΤϯυͰͷϢʔβʔͷೝূ BQJଆͰBVUI@JEΛ࢖༻͢Δ #[post("/api/buildings")] pub(crate) async fn create_building( request: web::Json, pool: web::Data, auth0_id: web::ReqData, ) -> ApiResult { let request = request.into_inner(); let building_info = BuildingInfo::try_from(request.building_info).invalid_request()?; verify_user(pool.as_ref(), &auth0_id.0).await?; let building_id = Building::insert(pool.as_ref(), &building_info) .await .log_db_err()?; Ok(web::Json(CreateBuildingResponse { building_id })) }

Slide 92

Slide 92 text

• Auth0×Actix_web×Next.jsでユーザー認証を⾏った • クライアントがAuth0サーバーから獲得したJWTトーク ンをRustバックエンドで検証してレスポンスを返す ·ͱΊ

Slide 93

Slide 93 text

͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠

Slide 94

Slide 94 text

ຊ೔͸͝ࢀՃ͍͖ͨͩ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ ڵຯΛ࣋ͨΕͨํ͸ͥͻ IUUQTKPCTFTUJFKQPS!JX@UBUTV ·Ͱʂ