Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OAuth 2.0 with Spring Security #jjug_ccc #jjug_ccc_b / oauth2-with-spring-security

OAuth 2.0 with Spring Security #jjug_ccc #jjug_ccc_b / oauth2-with-spring-security

JJUG CCC 2020 Fallでの講演資料です。Spring SecurityのOAuth 2.0機能について解説しています。OAuth 2.0自体は理解している前提の、中級者向け資料です。

5dbaf4015e7f249ab21b195ced8e9e46?s=128

Masatoshi Tada

November 07, 2020
Tweet

Transcript

  1. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 0"VUI XJUI 4QSJOH4FDVSJUZ ג ΧαϨΞϧଟాਅහ ೥݄೔

    ++6($$$'BMM 
  2. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ͜ͷηογϣϯʹ͍ͭͯ ▸ 4QSJOH4FDVSJUZͷ0"VUIؔ࿈ػೳΛɺ ࢓૊Έ΋ؚΊͯ෼͔Γ΍͘͢ղઆ͠·͢ ▸ αϯϓϧίʔυ

    ▸ IUUQTHJUIVCDPN.BTBUPTIJ5BEBPBVUIXJUI TQSJOHTFDVSJUZ 
  3. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ඞཁͳલఏ஌ࣝ ▸ ͜ͷηογϣϯ͸ʲதڃऀ޲͚ʳͰ͢ ▸ ҎԼͷલఏ஌͕ࣝඞཁͰ͢ ▸

    "VUIPSJ[BUJPO$PEF(SBOU'MPXΛઆ໌Ͱ͖Δ ▸ 4QSJOH4FDVSJUZΛ࢖ͬͨ͜ͱ͕͋Δ ▸ 0"VUIػೳͰͳͯ͘΋0, 
  4. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ઌʹ݁࿦ ▸ 4QSJOH4FDVSJUZ಺෦ͷRestTemplateʹ͸ɺ λΠϜΞ΢τ͕ઃఆ͞Ε͍ͯͳ͍͜ͱ͕ ΄ͱΜͲ ˠͪΌΜͱλΠϜΞ΢τΛઃఆ͠·͠ΐ͏

    
  5. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 0"VUIͷجૅΛ஌Γ͍ͨํ͸ʜ  https://www.slideshare.net/masatoshitada7/oauth-20spring-security-51-121418814

  6. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4QSJOH4FDVSJUZͷΞʔΩςΫνϟΛ஌Γ͍ͨํ͸ʜ  https://www.slideshare.net/masatoshitada7/spring-security-meetup

  7. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ࣗݾ঺հ ▸ ଟాਅහʢ!TVLF@NBTBʣ ▸ ݚमτϨʔφʔ!ΧαϨΞϧ ▸

    +BWB(PMBOH.JDSPTFSWJDFT ,VCFSOFUFT1ZUIPOػցֶश ▸ 7.XBSFೝఆߨࢣ ▸ ೔ຊ4QSJOHϢʔβձελοϑ 
  8. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ઌʹ͓࿳ͼ͓͖ͯ͠·͢ ▸ ່ࢯʢϲ݄ʣͷ੠͕ͱ͜ΖͲ͜ΖೖΔ͔΋ ͠Ε·ͤΜ 

  9. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc גࣜձࣾΧαϨΞϧ ▸ ଞࣾʹ͸ແ͍৭ʑͳϓϩάϥϛϯάݴޠͷ ݚमΛఏڙ͍ͯ͠·͢ʂ  /&8

  10. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4QSJOHܥίʔε  ▸ جૅ͔Βͷ4QSJOH#PPUʹΑΔ 8FCΞϓϦέʔγϣϯ։ൃʢ೔ؒʣ ▸

    7.XBSF5BO[Vೝఆ4QSJOH$PSF5SBJOJOHʢ೔ؒʣ ▸ 7.XBSF5BO[Vೝఆ4QSJOH$MPVE%FWFMPQFSʢ೔ؒʣ ▸ جૅ͔Βͷ4QSJOH4FDVSJUZʢ೔ؒʣ ▸ جૅ͔Βͷ4QSJOH#BUDIʢ೔ؒʣ
  11. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ৽نίʔεϦϦʔε  (PݴޠʹΑΔ Ϋϥ΢υωΠςΟϒΞϓϦέʔγϣϯ։ൃ جຊจ๏ɺ8FCΞϓϦέʔγϣϯɺϚΠΫϩαʔϏε 1ZUIPOೖ໳

    جຊจ๏ɺϥΠϒϥϦͷར༻ɺ8FCεΫϨΠϐϯά 1ZUIPOʹΑΔػցֶशೖ໳ʢԾʣ
  12. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΦϯϥΠϯݚमɺ͸͡Ί·ͨ͠  ߨࢣ डߨऀ༷ ▸ ʮֶशޮՌ͸௨ৗͱมΘΒͳ͍ʯ

    ͱ޷ධͰ͢ʂ
  13. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ໨࣍ ▸ 0"VUIΛβοͱ෮श ▸ ΫϥΠΞϯτͷجຊػೳͱߏ଄ ▸

    ΫϥΠΞϯτͰͷ8FC$MJFOUͷར༻ ▸ Ϧιʔεαʔόʔͷجຊػೳͱߏ଄ ▸ 5PLFO*OUSPTQFDUJPO ▸ 5PLFO1SPQBHBUJPO ▸ ·ͱΊ 
  14. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ໨࣍ ▸ 0"VUIΛβοͱ෮श ▸ ΫϥΠΞϯτͷجຊػೳͱߏ଄ ▸

    ΫϥΠΞϯτͰͷ8FC$MJFOUͷར༻ ▸ Ϧιʔεαʔόʔͷجຊػೳͱߏ଄ ▸ 5PLFO*OUSPTQFDUJPO ▸ 5PLFO1SPQBHBUJPO ▸ ·ͱΊ 
  15. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 0"VUIͱ͸ ▸ ೝՄͷྲྀΕΛنఆͨ͠ϓϩτίϧ ▸ 3'$ ೔ຊޠ൛΋͋Δ

     ▸ 0"VUIͱ͸ผ෺ ▸ 4USVUTͱ4USVUT͘Β͍ҧ͏ ▸ ೝূϓϩτίϧ0QFO*%$POOFDU ͷϕʔεʹͳ͍ͬͯΔ 
  16. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 0"VUIͷొ৔ਓ෺ ᶃ ϦιʔεΦʔφʔ 3FTPVSDF0XOFS  ▸

    ৘ใͷ࣋ͪओɻଟ͘ͷέʔεͰ͸ਓؒɻ ᶄ Ϧιʔεαʔόʔ 3FTPVSDF4FSWFS  ▸ ৘ใΛอ࣋͢Δαʔόʔɻ ᶅ ΫϥΠΞϯτ $MJFOU  ▸ Ϧιʔεαʔόʔ͔Β΋Βͬͨ৘ใΛѻ͏ΞϓϦέʔγϣϯɻ ᶆ ೝՄαʔόʔ "VUIPSJ[BUJPO4FSWFS  ▸ ΞΫηετʔΫϯΛൃߦ͢Δαʔόʔɻ 
  17. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 5XJUUFSͷྫͰొ৔ਓ෺·ͱΊ  twitter.com ͜Μʹͪ͸!
 ָ͠Έͩͳʔ Ϧιʔε


    Φʔφʔ ΫϥΠΞϯτ Ϧιʔεαʔόʔ ೝՄαʔόʔ ೝՄ ΞΫηε
 τʔΫϯ
 ෇༩ ΞΫηε
 τʔΫϯ ͭͿ΍͖ ※ຊ౰͸Twitter͸OAuth 1.0Λ࢖͍ͬͯ·͢
  18. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc άϥϯτλΠϓʢΞΫηετʔΫϯͷऔಘํ๏ʣ ᶃ ೝՄίʔυ ▸ ओʹαʔόʔαΠυ8FCΞϓϦέʔγϣϯ ᶄ

    ΠϯϓϦγοτʢඇਪ঑ʣ ▸ ओʹΫϥΠΞϯταΠυ8FCΞϓϦέʔγϣϯ ᶅ ϦιʔεΦʔφʔύεϫʔυΫϨσϯγϟϧʢඇਪ঑ʣ ▸ ओʹެࣜͷεϚϗΞϓϦͳͲ ᶆ ΫϥΠΞϯτΫϨσϯγϟϧ ▸ ΫϥΠΞϯτࣗ਎ͷ৘ใऔಘ 
  19. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc <ࢀߟ>0"VUIͷ࢓༷ࡦఆ͕ਐߦத ▸ 0"VUIͷ࢓༷ʴͦͷଞΛ࠶੔ཧͨ͠΋ͷ ˠطʹඇਪ঑ͱͳ͍ͬͯΔػೳ͕࡟আ͞ΕΔ ▸ ΠϯϓϦγοτ

    ▸ ϦιʔεΦʔφʔύεϫʔυΫϨσϯγϟϧ ▸ ৄࡉ͸ͪ͜Βͷهࣄ΁ ▸ 0"VUIͷඪ४Խ͕ਐΊΒΕ͍ͯ·͢ IUUQTRJJUBDPNqBOP@ZVLJJUFNTCGBFFFCFFEDD ▸ 4QSJOH4FDVSJUZͷ0"VUIରԠ༧ఆ͸ɺݱ࣌఺Ͱ͸ෆ໌ 
  20. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝՄίʔυʹΑΔΞΫηετʔΫϯऔಘ  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β※ ※Webϒϥ΢β͸ɺ࢓༷ॻͰ͸ʮϢʔβʔΤʔδΣϯτʯͱهࡌ͞Ε͍ͯ·͢ ᶃॳճΞΫηε
  21. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝՄίʔυʹΑΔΞΫηετʔΫϯऔಘ  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β※ ※Webϒϥ΢β͸ɺ࢓༷ॻͰ͸ʮϢʔβʔΤʔδΣϯτʯͱهࡌ͞Ε͍ͯ·͢ ᶃॳճΞΫηε ᶄೝՄΤϯυϙΠϯτʹϦμΠϨΫτ
  22. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝՄίʔυʹΑΔΞΫηετʔΫϯऔಘ  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β※ ※Webϒϥ΢β͸ɺ࢓༷ॻͰ͸ʮϢʔβʔΤʔδΣϯτʯͱهࡌ͞Ε͍ͯ·͢ ᶃॳճΞΫηε ᶄೝՄΤϯυϙΠϯτʹϦμΠϨΫτ ᶅೝՄը໘
  23. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝՄίʔυʹΑΔΞΫηετʔΫϯऔಘ  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β※ ※Webϒϥ΢β͸ɺ࢓༷ॻͰ͸ʮϢʔβʔΤʔδΣϯτʯͱهࡌ͞Ε͍ͯ·͢ ᶃॳճΞΫηε ᶄೝՄΤϯυϙΠϯτʹϦμΠϨΫτ ᶅೝՄը໘ ᶆೝՄ
  24. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝՄίʔυʹΑΔΞΫηετʔΫϯऔಘ  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β※ ※Webϒϥ΢β͸ɺ࢓༷ॻͰ͸ʮϢʔβʔΤʔδΣϯτʯͱهࡌ͞Ε͍ͯ·͢ ᶃॳճΞΫηε ᶇೝՄίʔυൃߦʴϦμΠϨΫτ ᶄೝՄΤϯυϙΠϯτʹϦμΠϨΫτ ᶅೝՄը໘ ᶆೝՄ
  25. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝՄίʔυʹΑΔΞΫηετʔΫϯऔಘ  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β※ ※Webϒϥ΢β͸ɺ࢓༷ॻͰ͸ʮϢʔβʔΤʔδΣϯτʯͱهࡌ͞Ε͍ͯ·͢ ᶃॳճΞΫηε ᶇೝՄίʔυൃߦʴϦμΠϨΫτ ᶈೝՄίʔυ ᶄೝՄΤϯυϙΠϯτʹϦμΠϨΫτ ᶅೝՄը໘ ᶆೝՄ
  26. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝՄίʔυʹΑΔΞΫηετʔΫϯऔಘ  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β※ ※Webϒϥ΢β͸ɺ࢓༷ॻͰ͸ʮϢʔβʔΤʔδΣϯτʯͱهࡌ͞Ε͍ͯ·͢ ᶃॳճΞΫηε ᶇೝՄίʔυൃߦʴϦμΠϨΫτ ᶈೝՄίʔυ ᶉΞΫηετʔΫϯ ᶄೝՄΤϯυϙΠϯτʹϦμΠϨΫτ ᶅೝՄը໘ ᶆೝՄ
  27. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΞΫηετʔΫϯΛར༻ͨ͠ϦιʔεΞΫηε  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε
 αʔόʔ ᶃϦΫΤετ
  28. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΞΫηετʔΫϯΛར༻ͨ͠ϦιʔεΞΫηε  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε
 αʔόʔ ᶃϦΫΤετ ᶄϦιʔεʹΞΫηε
 with ΞΫηετʔΫϯ
  29. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΞΫηετʔΫϯΛར༻ͨ͠ϦιʔεΞΫηε  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε
 αʔόʔ ᶃϦΫΤετ ᶅΞΫηε
 ɹτʔΫϯ
 ɹݕূ ᶄϦιʔεʹΞΫηε
 with ΞΫηετʔΫϯ
  30. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΞΫηετʔΫϯΛར༻ͨ͠ϦιʔεΞΫηε  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε
 αʔόʔ ᶃϦΫΤετ ᶅΞΫηε
 ɹτʔΫϯ
 ɹݕূ ᶆݕূ݁ՌΛฦ͢ ᶄϦιʔεʹΞΫηε
 with ΞΫηετʔΫϯ
  31. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΞΫηετʔΫϯΛར༻ͨ͠ϦιʔεΞΫηε  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε
 αʔόʔ ᶃϦΫΤετ ᶅΞΫηε
 ɹτʔΫϯ
 ɹݕূ ᶆݕূ݁ՌΛฦ͢ ᶇݕূ݁ՌΛ
 ɹ֬ೝ ᶄϦιʔεʹΞΫηε
 with ΞΫηετʔΫϯ
  32. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΞΫηετʔΫϯΛར༻ͨ͠ϦιʔεΞΫηε  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε
 αʔόʔ ᶃϦΫΤετ ᶅΞΫηε
 ɹτʔΫϯ
 ɹݕূ ᶆݕূ݁ՌΛฦ͢ ᶈϨεϙϯε ᶇݕূ݁ՌΛ
 ɹ֬ೝ ᶄϦιʔεʹΞΫηε
 with ΞΫηετʔΫϯ
  33. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΞΫηετʔΫϯΛར༻ͨ͠ϦιʔεΞΫηε  ೝՄαʔόʔ ΫϥΠΞϯτ Ϧιʔε
 Φʔφʔ

    Web
 ϒϥ΢β ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε
 αʔόʔ ᶃϦΫΤετ ᶅΞΫηε
 ɹτʔΫϯ
 ɹݕূ ᶆݕূ݁ՌΛฦ͢ ᶈϨεϙϯε ᶉϨεϙϯε ᶇݕূ݁ՌΛ
 ɹ֬ೝ ᶄϦιʔεʹΞΫηε
 with ΞΫηετʔΫϯ
  34. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ໨࣍ ▸ 0"VUIΛβοͱ෮श ▸ ΫϥΠΞϯτͷجຊػೳͱߏ଄ ▸

    ΫϥΠΞϯτͰͷ8FC$MJFOUͷར༻ ▸ Ϧιʔεαʔόʔͷجຊػೳͱߏ଄ ▸ 5PLFO*OUSPTQFDUJPO ▸ 5PLFO1SPQBHBUJPO ▸ ·ͱΊ 
  35. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ґଘੑ  <dependency> <groupId>org.springframework.boot</groupId> <artifactId> spring-boot-starter-oauth2-client

    </artifactId> </dependency> wTQSJOHTFDVSJUZDPOpH wTQSJOHTFDVSJUZPBVUIDMJFOU ͳͲؚ͕·Ε͍ͯΔ
  36. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc BQQMJDBUJPOZNM  spring.security.oauth2.client.registration.todo: provider: ೚ҙͷ໊લ(.registrationͷޙʹ΋ࢦఆ͢Δ) client-id:

    ΫϥΠΞϯτID client-secret: ΫϥΠΞϯτγʔΫϨοτ client-name: ೚ҙͷ໊લ(ը໘දࣔͰ࢖ΘΕΔ) client-authentication-method: ΫϥΠΞϯτೝূํ๏ authorization-grant-type: άϥϯτλΠϓ redirect-uri: ϦμΠϨΫτΤϯυϙΠϯτͷURL scope: ͜ͷΞϓϦͷείʔϓΛΧϯϚ۠੾ΓͰࢦఆ ※εϖʔεͷ౎߹্ͰYAMLܗࣜͰॻ͍͍ͯ·͕͢ɺݸਓతʹ͸properties೿Ͱ͢
  37. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc BQQMJDBUJPOZNMʢଓ͖ʣ  spring.security.oauth2.client.provider.todo: authorization-uri: ೝՄΤϯυϙΠϯτͷURL token-uri:

    τʔΫϯΤϯυϙΠϯτͷURL user-info-uri: Ϣʔβʔ৘ใͷJSON͕ฦͬͯ͘ΔURL user-name-attribute: JSONͷதͷϢʔβʔ໊Λද͢ଐੑ໊ user-info-authentication-method: Ϣʔβʔ৘ใऔಘ࣌ͷೝূํࣜ jwk-set-uri: JWK Set͕ฦͬͯ͘ΔURL issuer-uri: ೝՄαʔόʔͷIssuer Identifier ※Keycloakͷ৔߹ɺissuer-uriΛࢦఆ͢Ε͹ଞͷϓϩύςΟ͸ࢦఆෆཁʢuser-name-attribute͸೚ҙʣ
  38. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc +BWB$POpH  @EnableWebSecurity public class SecurityConfig

    extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.oauth2Login() .loginPage("/login") .permitAll(); ... } } ϩάΠϯʹؔ͢Δઃఆ
  39. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4QSJOH4FDVSJUZ'JMUFS$IBJO  SecurityContextPersistenceFilter LogoutFilter OAuth2AuthorizationRequestRedirectFilter OAuth2LoginAuthenticationFilter

    ExceptionTranslationFilter FilterSecurityInterceptor ϦΫΤετ ೝՄΤϯυϙΠϯτʹ ϦμΠϨΫτ͢Δ ೝূΛߦ͏
  40. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 0"VUI"VUIPSJ[BUJPO3FRVFTU3FEJSFDU'JMUFS ▸ ೝՄ͕ඞཁͳ৔߹ɺೝՄαʔόʔͷ ೝՄΤϯυϙΠϯτʹϦμΠϨΫτ͍ͯ͠Δ  @Override

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestResolver.resolve(request); if (authorizationRequest != null) { this.sendRedirectForAuthorization( request, response, authorizationRequest); return; } ... https://github.com/spring-projects/spring-security/blob/master/oauth2/ oauth2-client/src/main/java/org/springframework/security/oauth2/ client/web/OAuth2AuthorizationRequestRedirectFilter.java#L164
  41. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 0"VUI-PHJO"VUIFOUJDBUJPO'JMUFS಺Ͱͷॲཧ  OAuth2LoginAuthenticationFilter ProviderManager OidcAuthorizationCodeAuthenticationProvider DefaultAuthoriaztionCodeTokenResponseClient

    ᶃೝՄίʔυΛड͚औΔ ᶄೝՄίʔυΛ࣋ͬͨ ɹAuthenticationΛ౉͢ ᶅೝՄίʔυΛ࣋ͬͨ ɹAuthenticationΛ౉͢ ᶆݺͼग़͠ ᶇOAuth2AccessToken ɹResponseΛฦ͢ ᶈ+85͔Β"VUIPSJUZΛநग़ɹ ɹˠAuthenticationΛฦ͢ ᶉAuthenticationΛฦ͢ ᶊSecurityContextʹɹ ɹAuthenticationΛอଘ
  42. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc %FGBVMU"VUIPSJ[BUJPO$PEF5PLFO3FTQPOTF$MJFOU ▸ RestTemplateͰೝՄαʔόʔʹ ΞΫηεͯ͠ɺΞΫηετʔΫϯͷऔಘΛߦ͏ ▸ ͜ͷRestTemplateʹ͸ɺσϑΥϧτͰ͸

    λΠϜΞ΢τ͕ઃఆ͞Ε͍ͯͳ͍ 
  43. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc +BWB$POpHʹઃఆΛ௥Ճ  private DefaultAuthorizationCodeTokenResponseClient client() {

    RestTemplate restTemplate = restTemplateBuilder // λΠϜΞ΢τΛઃఆ .setConnectTimeout(Duration.ofMillis(1000)) .setReadTimeout(Duration.ofMillis(1000)) ... .build(); DefaultAuthorizationCodeTokenResponseClient client = new DefaultAuthorizationCodeTokenResponseClient(); // λΠϜΞ΢τઃఆࡁΈͷRestTemplateΛઃఆ client.setRestOperations(restTemplate); return client; }
  44. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc +BWB$POpHͷઃఆΛมߋ  @Override protected void configure(HttpSecurity

    http) throws Exception { http.oauth2Login(oauth2 -> oauth2 // λΠϜΞ΢τઃఆࡁΈͷTokenResponseClientΛࢦఆ .tokenEndpoint(token -> token .accessTokenResponseClient(client()) ) ... .loginPage("/login") .permitAll() ).authorizeRequests(auth -> auth ... ˞εϥΠυͰ͸εϖʔεͷ౎߹্ׂѪ͍ͯ͠·͕͢ɺOAuth2UserService΍ ɹOidcUserServiceʹ΋ಉ༷ͷઃఆ͕ඞཁͰ͢ʢৄࡉ͸(JU)VCࢀরʣ
  45. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ໨࣍ ▸ 0"VUIΛβοͱ෮श ▸ ΫϥΠΞϯτͷجຊػೳͱߏ଄ ▸

    ΫϥΠΞϯτͰͷ8FC$MJFOUͷར༻ ▸ Ϧιʔεαʔόʔͷجຊػೳͱߏ଄ ▸ 5PLFO*OUSPTQFDUJPO ▸ 5PLFO1SPQBHBUJPO ▸ ·ͱΊ 
  46. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 8FC$MJFOUͱ͸ʁ ▸ 4QSJOH8FC'MVYʹؚ·Ε͍ͯΔɺ ϦΞΫςΟϒͳ)551ΫϥΠΞϯτ ▸ 3FBDUPSͷ'MVY.POPΛ׆༻

    ▸ ྲྀΕΔΑ͏ͳ"1*  public List<Todo> findAll() { return webClient.get() .uri("/todos") .retrieve() .bodyToFlux(Todo.class) .collectList() .block(); }
  47. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 3FTU5FNQMBUFͷ+BWBEPDΑΓ  https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/ RestTemplate.html ɾҎ߱Ͱ͸ϝϯςφϯεϞʔυ΍Ͱ ɾ୅ΘΓʹ8FC$MJFOUͷར༻Λݕ౼ͯ͠΍

  48. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 8FC$MJFOUʹҠߦ͢΂͖͔ʁ ▸ ·ͩ࢑͘͸3FTU5FNQMBUFͰΑ͍ ଟాݸਓͷҙݟ  ▸

    ΞϓϦέʔγϣϯ΍4QSJOHຊମͳͲ΁ͷӨڹ͕ඇৗʹେ͖͍ ͨΊɺ3FTU5FNQMBUF͕͙͢ʹ࡟আ͞ΕΔͱ͸ࢥ͑ͳ͍ ▸ 8FC$MJFOUΛ࢖͏ͱɺͲ͏ͯ͠΋'MVY.POPΛ࢖ͬͨ ϦΞΫςΟϒϓϩάϥϛϯάΛҙࣝ͠ͳ͚Ε͹ͳΒͳ͍ͨΊɺ ೉қ౓্͕͕Δ ▸ ͜ͷઅͰ͸͋͘·Ͱʮ8FC$MJFOUΛ࢖͏ͱ͜͏ͳΔΑʯ ͱ͍͏ྫΛ঺հ 
  49. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 8FC$MJFOUΛ4QSJOH.7$্Ͱ࢖͏  <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> ▸ TQSJOHCPPUTUBSUFSXFC .7$ ͱ TQSJOHCPPUTUBSUFSXFCqVY 8FC'MVY ͷ྆ํΛ ґଘੑʹؚΊΔͱɺ4QSJOH.7$͕༏ઌ͞ΕΔ ▸ IUUQTEPDTTQSJOHJPTQSJOHCPPUEPDTDVSSFOUSFGFSFODF IUNMTJOHMFCPPUGFBUVSFTXFCFOWJSPONFOU
  50. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 8FC$MJFOUͷ#FBOఆٛ  @Bean public WebClient webClient(...)

    { // λΠϜΞ΢τΛઃఆ Function<? super TcpClient, ? extends TcpClient> tcpMapper = tcpClient -> { // Connect TimeoutΛઃఆ return tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000) .doOnConnected(conn -> conn // Read TimeoutΛઃఆ .addHandlerLast( new ReadTimeoutHandler(1000, TimeUnit.MILLISECONDS)) // Write TimeoutΛઃఆ .addHandlerLast( new WriteTimeoutHandler(1000, TimeUnit.MILLISECONDS)) ); }; // ࣍ϖʔδʹଓ͘ λΠϜΞ΢τઃఆΛ๨Εͣʹʂ
  51. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 8FC$MJFOUͷ#FBOఆٛʢଓ͖ʣ  // લϖʔδ͔Βͷଓ͖ HttpClient httpClient

    = HttpClient.create().tcpConfiguration(tcpMapper); // OAuth2ؔ࿈ͷઃఆ ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction( clientRegistrationRepository, authorizedClientRepository); return builder.baseUrl(resourceServerUri) // ࡞੒ͨ͠HttpClientΛ௥Ճ .clientConnector(new ReactorClientHttpConnector(httpClient)) // OAuth2ઃఆΛ௥Ճ .apply(oAuth2Client.oauth2Configuration()) ... .build(); }
  52. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4FSWMFU0"VUI"VUIPSJ[FE$MJFOU &YDIBOHF'JMUFS'VODUJPO͸ԿΛͯ͘͠ΕΔ͔ ▸ 8FC$MJFOU͔ΒͷϦΫΤετ࣌ʹ Authorization: Bearer

    ΞΫηετʔΫϯ Λϔομʔʹ௥Ճͯ͘͠ΕΔ ▸ ΞΫηετʔΫϯͷ༗ޮظݶ͕੾Ε͍ͯͨΒ ϦϑϨογϡͯ͘͠ΕΔ 
  53. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ϦϑϨογϡͷ࢓૊Έ  ServletOAuth2AuthorizedClientExchangeFilterFunction DefaultOAuth2AuthorizedClientManager DelegatingOAuth2AuthorizedClientProvider RefreshTokenOAuth2AuthorizedClientProvider

    DefaultRefreshTokenTokenResponseClient ݺͼग़͠ ݺͼग़͠ ݺͼग़͠ ݺͼग़͠
  54. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc %FGBVMU3FGSFTI5PLFO5PLFO3FTQPOTF$MJFOU ▸ 3FTU5FNQMBUFͰೝՄαʔόʔʹΞΫηεͯ͠ɺ ΞΫηετʔΫϯͷϦϑϨογϡΛߦ͏ ▸ ৄࡉ͸Լهͷهࣄࢀর

    ▸ 4QSJOH4FDVSJUZYͰ0"VUIΞΫηετʔΫϯΛ ϦϑϨογϡ͢Δ IUUQTRJJUBDPNTVLF@NBTBJUFNT GCGDFCF 
  55. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc %FGBVMU3FGSFTI5PLFO5PLFO3FTQPOTF$MJFOU ͷ஫ҙ఺ ▸ σϑΥϧτͰ͸ɺ ಺෦Ͱ࢖͍ͬͯΔRestTemplateʹ λΠϜΞ΢τ͕ઃఆ͞Ε͍ͯͳ͍

    ˠԼهͷΑ͏ʹઃఆ  DefaultRefreshTokenTokenResponseClient tokenResponseClient = new DefaultRefreshTokenTokenResponseClient(); RestTemplate restTemplate = restTemplateBuilder .setConnectTimeout(Duration.ofMillis(1000)) .setReadTimeout(Duration.ofMillis(1000)) ... .build(); tokenResponseClient.setRestOperations(restTemplate);
  56. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4FSWMFU0"VUI"VUIPSJ[FE$MJFOU &YDIBOHF'JMUFS'VODUJPOʹλΠϜΞ΢τΛઃఆ  ServletOAuth2AuthorizedClientExchangeFilterFunction DefaultOAuth2AuthorizedClientManager OAuth2AuthorizedClientProvider

    RestTemplateʢλΠϜΞ΢τઃఆࡁΈʣ ୅ೖ ୅ೖ ୅ೖ ୅ೖ DefaultRefreshTokenTokenResponseClient
  57. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4FSWMFU0"VUI"VUIPSJ[FE$MJFOU &YDIBOHF'JMUFS'VODUJPOʹλΠϜΞ΢τΛઃఆ  ▸ ۩ମతͳίʔυ͸ϝνϟ௕͍ͷͰ(JU)VCࢀর ▸

    IUUQTHJUIVCDPN.BTBUPTIJ5BEBPBVUIXJUI TQSJOHTFDVSJUZCMPCNBTUFSDMJFOUKXUTSDNBJO KBWBDPNFYBNQMFDMJFOUKXU $MJFOU+XU"QQMJDBUJPOKBWB-
  58. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc *TTVFཱͯ·ͨ͠ ▸ ੋඇʮ͍͍Ͷʯ͍ͩ͘͞ ▸ IUUQTHJUIVCDPNTQSJOHQSPKFDUTTQSJOHTFDVSJUZ JTTVFT

    
  59. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ໨࣍ ▸ 0"VUIΛβοͱ෮श ▸ ΫϥΠΞϯτͷجຊػೳͱߏ଄ ▸

    ΫϥΠΞϯτͰͷ8FC$MJFOUͷར༻ ▸ Ϧιʔεαʔόʔͷجຊػೳͱߏ଄ ▸ 5PLFO*OUSPTQFDUJPO ▸ 5PLFO1SPQBHBUJPO ▸ ·ͱΊ 
  60. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ґଘੑ  <dependency> <groupId>org.springframework.boot</groupId> <artifactId> spring-boot-starter-oauth2-resource-server

    </artifactId> </dependency> wTQSJOHTFDVSJUZDPOpH wTQSJOHTFDVSJUZPBVUISFTPVSDFTFSWFS wTQSJOHTFDVSJUZPBVUIKPTF ͳͲؚ͕·Ε͍ͯΔ
  61. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc BQQMJDBUJPOZNM  spring.security.oauth2.resourceserver.jwt: jwk-set-uri: JWK Set͕ฦͬͯ͘ΔURL

    issuer-uri: ೝՄαʔόʔͷIssuer Identifier ※Keycloakͷ৔߹ɺissuer-uriΛࢦఆ͢Ε͹jwk-set-uri͸ࢦఆෆཁ
  62. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc +BWB$POpH  @EnableWebSecurity public class SecurityConfig

    extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { ... http.authorizeRequests() .mvcMatchers("อޢର৅ͷURL") .hasAuthority("SCOPE_είʔϓ໊") ...; http.oauth2ResourceServer() .jwt(); ... } }
  63. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4QSJOH4FDVSJUZ'JMUFS$IBJO  SecurityContextPersistenceFilter LogoutFilter BearerTokenAuthenticationFilter ExceptionTranslationFilter

    FilterSecurityInterceptor ϦΫΤετ ड৴ͨ͠+85Λ࢖ͬͯ ೝূ͢Δ
  64. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc #FBSFS5PLFO"VUIFOUJDBUJPO'JMUFS಺Ͱͷॲཧ  BearerTokenAuthenticationFilter ProviderManager JwtAuthenticationProvider NimbusJwtDecoder

    ᶃϦΫΤετϔομʔͰ ɹ+85จࣈྻΛड͚औΔ ᶄ+85จࣈྻΛ࣋ͬͨ ɹ"VUIFOUJDBUJPOΛ౉͢ ᶅ+85จࣈྻΛ࣋ͬͨ ɹ"VUIFOUJDBUJPOΛ౉͢ ᶆ+85จࣈྻΛ౉͢ ᶇ+85จࣈྻΛݕূޙɺ ɹ+XUΦϒδΣΫτʹม׵ ᶈ+XU͔Β"VUIPSJUZΛநग़ɹ ɹˠ"VUIFOUJDBUJPOΛฦ͢ ᶉ"VUIFOUJDBUJPOΛฦ͢ ᶊ4FDVSJUZ$POUFYUʹɹ ɹ"VUIFOUJDBUJPOΛอଘ ݕূࣦഊ࣌͸ ྫ֎ൃੜ
  65. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ໨࣍ ▸ 0"VUIΛβοͱ෮श ▸ ΫϥΠΞϯτͷجຊػೳͱߏ଄ ▸

    ΫϥΠΞϯτͰͷ8FC$MJFOUͷར༻ ▸ Ϧιʔεαʔόʔͷجຊػೳͱߏ଄ ▸ 5PLFO*OUSPTQFDUJPO ▸ 5PLFO1SPQBHBUJPO ▸ ·ͱΊ 
  66. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc +85ܗࣜΞΫηετʔΫϯͷ໰୊఺ ▸ +85ʹؚ·Ε͍ͯͳ͍৘ใ͸औಘͰ͖ͳ͍ ▸ +85ʹؚΉ৘ใ͕ଟ͗͢Δͱ τʔΫϯࣗମ͕େ͖͘ͳͬͯ͠·͏

    ▸ ೝՄαʔόʔଆͰ ΞΫηετʔΫϯΛແޮԽͰ͖ͳ͍ 
  67. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ͦ͜Ͱ5PLFO*OUSPTQFDUJPOʂ ▸ 3'$ ▸ IUUQTUPPMTJFUGPSHIUNMSGD ▸

    Ϧιʔεαʔόʔ͕ೝՄαʔόʔʹ ΞΫηετʔΫϯΛૹ৴͢Δ͜ͱͰɺ ᶃΞΫηετʔΫϯࣗମʹؚ·Ε͍ͯͳ͍৘ใΛ औಘͰ͖Δ ᶄΞΫηετʔΫϯͷ༗ޮੑΛνΣοΫͰ͖Δ 
  68. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ϦΫΤετ  ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε αʔόʔ

    ೝՄ αʔόʔ POST /introspect HTTP/1.1 Host: keycloak.example.com Accept: application/json Content-Type: application/x-www-form-urlencoded Authorization: Basic dXNlcjpwYXNzd29yZAo= token=ΞΫηετʔΫϯ
  69. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc Ϩεϙϯε  ੥ٻॻ࡞੒
 ࢿྉ༣ૹ Ϧιʔε αʔόʔ

    ೝՄ αʔόʔ HTTP/1.1 200 OK Content-Type: application/json { "active": true·ͨ͸false, "client_id": "ΫϥΠΞϯτͷID", "username": "ϦιʔεΦʔφʔͷϢʔβʔ໊", "scope": "είʔϓ", ... }
  70. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc Ϧιʔεαʔόʔͷೝূํ๏ ▸ ۩ମతͳํ๏͸ɺ࢓༷Ͱ͸ఆ·͍ͬͯͳ͍ ▸ 4QSJOH4FDVSJUZͷσϑΥϧτ͸#BTJDೝূ ▸

    NimbusOpaqueTokenIntospector͕ RestTemplateΛ࢖࣮ͬͯߦ ▸ ଞͷํ๏ʹΧελϚΠζՄೳʢޙड़ʣ 
  71. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc BQQMJDBUJPOZNM  spring.security.oauth2.resourceserver.opaquetoken: client-id: ϦιʔεαʔόʔͷID client-secret:

    Ϧιʔεαʔόʔͷύεϫʔυ introspection-uri: ೝՄαʔόʔͷ ɹɹɹɹɹɹɹɹɹɹɹɹ ΠϯτϩεϖΫγϣϯΤϯυϙΠϯτ
  72. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc +BWB$POpH  @EnableWebSecurity public class SecurityConfig

    extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.oauth2ResourceServer() .opaqueToken(); } }
  73. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4QSJOH4FDVSJUZ'JMUFS$IBJO  SecurityContextPersistenceFilter LogoutFilter BearerTokenAuthenticationFilter ExceptionTranslationFilter

    FilterSecurityInterceptor ϦΫΤετ ड৴ͨ͠ΞΫηετʔΫϯΛ ࢖ͬͯೝূ͢Δ
  74. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc #FBSFS5PLFO"VUIFOUJDBUJPO'JMUFS಺Ͱͷॲཧ  BearerTokenAuthenticationFilter ProviderManager OpaqueTokenAuthenticationProvider NimbusOpaqueTokenIntrospector

    ᶃϦΫΤετϔομʔͰ ɹΞΫηετʔΫϯΛड͚औΔ ᶄΞΫηετʔΫϯΛ࣋ͬͨ ɹ"VUIFOUJDBUJPOΛ౉͢ ᶅΞΫηετʔΫϯΛ࣋ͬͨ ɹ"VUIFOUJDBUJPOΛ౉͢ ᶆΞΫηετʔΫϯΛ౉͢ ᶇ5PLFO*OUSPTQFDUJPO࣮ߦ ɹˠ0"VUI"VUIFOUJDBUJPO ɹɹ1SJODJQBMΛฦ͢ ᶈ"VUIFOUJDBUJPOΛฦ͢ ᶉ"VUIFOUJDBUJPOΛฦ͢ ᶊ4FDVSJUZ$POUFYUʹɹ ɹ"VUIFOUJDBUJPOΛอଘ ݕূࣦഊ࣌͸ ྫ֎ൃੜ
  75. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝূํ๏ͷΧελϚΠζ  @EnableWebSecurity public class SecurityConfig

    extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.oauth2ResourceServer() .opaqueToken() .introspector(new MyIntrospector()); } } public class MyIntrospector implements OpaqueTokenIntrospector { ... }
  76. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΧελϚΠζྫ  ▸ NimbusOpaqueTokenIntospector಺ͷ RestTemplateʹλΠϜΞ΢τΛઃఆ ▸

    σϑΥϧτͰ͸λΠϜΞ΢τແ͠ͳͷͰɺ ઃఆͨ͠΄͏͕Α͍
  77. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΧελϚΠζྫ  @Configuration public class IntrospectorConfig

    { @Bean public NimbusOpaqueTokenIntrospector introspector( RestTemplateBuilder builder, OAuth2ResourceServerProperties prop) { OAuth2ResourceServerProperties.Opaquetoken opaquetoken = prop.getOpaquetoken(); RestTemplate rest = builder .setReadTimeout(Duration.ofMillis(1000)) .setConnectTimeout(Duration.ofMillis(1000)) .basicAuthentication(opaquetoken.getClientId(), opaquetoken.getClientSecret()) .build(); return new NimbusOpaqueTokenIntrospector( opaquetoken.getOpaquetoken().getIntrospectionUri(), rest); } } λΠϜΞ΢τઃఆࡁΈͷ RestTemplateΛར༻͢Δ NimbusOpaqueToken IntrospectorΛ#FBOఆٛ
  78. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ΧελϚΠζྫ  @EnableWebSecurity public class SecurityConfig

    extends WebSecurityConfigurerAdapter { @Autowired OpaqueTokenIntrospector introspector; @Override protected void configure(HttpSecurity http) throws Exception { http.oauth2ResourceServer() .opaqueToken() .introspector(introspector); } ΧελϚΠζͨ͠ NimbusOpaqueTokenIntrospector ͷ#FBOΛࢦఆ
  79. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ໨࣍ ▸ 0"VUIΛβοͱ෮श ▸ ΫϥΠΞϯτͷجຊػೳͱߏ଄ ▸

    ΫϥΠΞϯτͰͷ8FC$MJFOUͷར༻ ▸ Ϧιʔεαʔόʔͷجຊػೳͱߏ଄ ▸ 5PLFO*OUSPTQFDUJPO ▸ 5PLFO1SPQBHBUJPO ▸ ·ͱΊ 
  80. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 5PLFO1SPQBHBUJPOͱ͸ ▸ தؒͷϚΠΫϩαʔϏε͸ɺ ࣗ෼͕ड͚औͬͨΞΫηετʔΫϯΛ ͦͷ··ԼྲྀͷϚΠΫϩαʔϏεʹ౉͢ 

    $MJFOU "1* (BUFXBZ 3FTPVSDF 4FSWFS ΞΫηε τʔΫϯ ΞΫηε τʔΫϯ
  81. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 5PLFO1SPQBHBUJPOͷઃఆ ▸ WebClientʹ ServletBearerExchangeFilterFunction Λ௥Ճ 

    @Bean public WebClient webClient(...) { ... return builder.baseUrl(resourceServerUri) .clientConnector(new ReactorClientHttpConnector(httpClient)) .filter(new ServletBearerExchangeFilterFunction()) ... .build(); }
  82. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 5PLFO1SPQBHBUJPOͷ࢓૊Έ ▸ ϦΫΤετૹ৴લʹ ᶃ "VUIFOUJDBUJPO͔ΒΞΫηετʔΫϯΛऔಘ ᶄ

    "VUIPSJ[BUJPOϔομʔʹΞΫηετʔΫϯΛ௥Ճ ‣ ৄࡉ͸͜͜Β΁Μͷίʔυࢀর ‣ IUUQTHJUIVCDPNTQSJOHQSPKFDUTTQSJOHTFDVSJUZCMPC NBTUFSPBVUIPBVUISFTPVSDFTFSWFSTSDNBJOKBWBPSH TQSJOHGSBNFXPSLTFDVSJUZPBVUITFSWFSSFTPVSDFXFC SFBDUJWFGVODUJPODMJFOU 4FSWMFU#FBSFS&YDIBOHF'JMUFS'VODUJPOKBWB- 
  83. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 3FTU5FNQMBUFΛ࢖͍͍ͨ৔߹ ▸ ಉ౳ͷػೳΛࣗ෼Ͱ࡞Δඞཁ͕͋Δ ▸ ίʔυྫ͸ϦϑΝϨϯεࢀর IUUQTEPDTTQSJOHJPTQSJOHTFDVSJUZTJUFEPDT

    3&-&"4&SFGFSFODFIUNMSFTUUFNQMBUF TVQQPSU 
  84. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ໨࣍ ▸ 0"VUIΛβοͱ෮श ▸ ΫϥΠΞϯτͷجຊػೳͱߏ଄ ▸

    ΫϥΠΞϯτͰͷ8FC$MJFOUͷར༻ ▸ Ϧιʔεαʔόʔͷجຊػೳͱߏ଄ ▸ 5PLFO*OUSPTQFDUJPO ▸ 5PLFO1SPQBHBUJPO ▸ ·ͱΊ 
  85. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ·ͱΊ ▸ λΠϜΞ΢τઃఆɺେࣄɻ 

  86. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ೝՄαʔόʔ͸ʁ ▸ 4QSJOH"VUIPSJ[BUJPO4FSWFS͕։ൃਐߦத  https://spring.io/blog/2020/08/21/get-the-very-first-bits-of-spring-authorization-server-0-0-1

  87. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 4QSJOH4FDVSJUZϦϑΝϨϯε ▸ ࠓճ঺հ͍ͯ͠ͳ͍ػೳ΍ɺ༷ʑͳΧελϚΠζ ํ๏͕঺հ͞Ε͍ͯ·͢ ▸ IUUQTEPDTTQSJOHJPTQSJOHTFDVSJUZTJUF

    EPDT3&-&"4&SFGFSFODFIUNM PBVUI 
  88. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 0"VUIؔ࿈ॻ੶ 

  89. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc 0"VUI࢓༷ॻ ▸ 3'$5IF0"VUI"VUIPSJ[BUJPO 'SBNFXPSL ▸ IUUQTUPPMTJFUGPSHIUNMSGD

    ▸ 3'$0"VUI5PLFO*OUSPTQFDUJPO ▸ IUUQTUPPMTJFUGPSHIUNMSGD 
  90. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc <3*1>౎ݩ͞Μͷࢿྉ ▸ ϚΠΫϩαʔϏε࣌୅ͷೝূͱೝՄ ▸ IUUQTXXXTMJEFTIBSFOFUEBJTVLF@N TT

    ▸ جૅ͔Βͷ0"VUI ▸ IUUQTXXXTMJEFTIBSFOFUEBJTVLF@NPBVUI EFWFMPQFSTJP 
  91. $ $"4"3&"- *OD"MMSJHIUTSFTFSWFE #jjug_ccc ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ