Working with Azure Episode 1: Secure your Spring boot application with Oauth2 + Azure Active Directory (Part 1: Authentication)

Chan Suttichujit
NonTechCompany
Published in
3 min readJun 29, 2020

Introduction

สวัสดีครับบทความนี้จะเป็นตอนแรกของซีรีย์ Working with Azure ซึ่งเราจะเจาะลึก tools และ approach ต่างๆที่ใช้ในการ Develop web application จากบทความ Tech stack ของ ExxonMobil ที่พี่ Tanat Lokejaroenlarb และผมเขียนขึ้นมา Tech Stack ของ ExxonMobil และใน EP แรกนี้เราจะมาดูกันว่าการทำให้ Web service ของเราปลอดภัยนั้นต้องเริ่มจากอะไรกัน?

Authentication and Authorization

เกริ่นคร่าวๆนั้นการสร้าง Web Service ต้องมีการตรวจสอบและจำกัดสิทธิในการเข้าถึง Endpoint แต่ละอันซึ่งอาจจะมีกลุ่มผู้ใช้ที่แตกต่างกันซึ่งแบ่งได้เป็นสองส่วนคือ Authentication และ Authorization

Authentication: การตรวจสอบ identity ของ client ว่าคนๆใช่คนที่เรารู้จักหรือไม่

Authorization: การตรวจสอบ access ของ client ว่าคนๆนี้มีสิทธิที่จะเข้าถึงข้อมูลของ endpoint นั้นๆหรือไม่

ในที่นี้เราจะเลือกใช้ Oauth2 ในการทำ Authentication and Authorization เนื่องจากเป็น Protocol ที่เป็น stardard และใช้กันแพร่หลายในการ Secure Application

Oauth2

การที่ Client จะสามารถ Authenticate เข้า service เราผ่าน Oauth2 นั้น ต้องมีสิ่งที่เรียกว่า Bearer Token แนบมากับ Authorization header ซึ่งเป็น Jwt มีข้อมูลของ Client อยู่ซึ่งมีด้วยกันหลาย Flow อาทิ เช่น Client Credentials, Authorization Code, Implicit, etc. ข้อมูลเพิ่มเติมที่: https://oauth.net/2/grant-types/

ซึ่งในวันนี้ผมขอเลือกใช้ Client Credentials Grant เพื่อสาธิตในส่วนของ resource server ว่าเราจะทำอย่างไรเพื่อดักจับ และ validate Oauth2 token ที่ได้รับมาจาก Client

รูปด้านล่างคือการทำงานของ Client Credentials Flow แบบคร่าวๆ

Credit: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow

Create AzureAD application

ขั้นแรกเราจะทำการสร้าง application บน AzureAD ขึ้นมา 2 ตัว

ตัวที่หนึ่งจะเป็นตัวแทน Resource Server

ตัวที่สองจะเป็นตัวแทนของ Client Application

วิธีสร้าง Application บน Azure AD: https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal

Gradle Dependencies

Dependencies ที่ต้องใช้มีแค่ 2 ตัว

ตัวแรกใช้ในการสร้าง Web Service ของ Spring Boot

spring-boot-starter-web

ตัวที่สองเอาไว้ใช้สำหรับ Oauth2 configuration ของ Spring Boot

spring-starter-oauth2-resource-server

Hello AzureAD Endpoint

สร้าง Endpoint ง่ายๆขึ้นมาตัวหนึ่งซึ่ง return response เป็น String

Oauth2 Configuration

ระบุ issuer-uri และ jwt-set-uri ซึ่งก็คือ endpoint ของ Azure AD ที่ใช้ในการ validate Jwt Token signature และ issuer

YOUR_TENANT_ID: Tenant Id ของ AzureAD application ที่เราสร้างขึ้นมาเรียบร้อยแล้ว

สร้าง configuration class ของ Oauth2

  • http.authorizeRequest: เลือก endpoint ที่ต้องการ secure อย่างเช่นในที่นี้ a.antMatchers(“/azuread”) จะทำการ match endpoint /azuread และตามด้วย .fullyAuthenticated() เพื่อบอกว่าเราต้องการที่จะให้มีการ authenticate ที่ endpoint ที่matchกับpattern
  • .exceptionHandling: เพื่อสร้างตัว handler เวลาที่ authenticate ไม่ผ่านจะ return Https Status 401 กลับไป
  • .oauth2ResoureceServer().jwt: เพื่อบอกว่าเราจะใช้ oauth2 protocol ในการทำ authentication ตัว Spring จะทำการ validate Jwt ตาม configuration ที่เราใส่ไว้ใน application.yaml

Your endpoint is secured

ทีนี้ลองใช้ Postman ยิงไปที่ localhost:8080/azuread จะเห็นได้ว่า Response Status ที่ได้กลับมาจะเป็น 401 Unauthorized เนื่องจากเรายังไม่ได้ทำการแนบ Bearer Token ไปกับ header

คราวนี้เราจะทำการแนบ Token ไปกับ header ด้วย

ขั้นแรกเราต้องไปขอ Access Token มาก่อนโดนการยิง request ไปที่ endpoint ดังนี้

CLIENT_APPLICATION_ID: Client Id ของ AzureAD application ที่เป็นตัวแทนของ Client

CLIENT_APPLICATION_SECRET: Secret ของ AzureAD application ที่เป็นตัวแทนของ Client

RESOURCE_APPLICATION_ID: Client Id ของ AzureAD application ที่เป็นตัวแทนของ Resource Server

POST /{tenant}/oauth2/v2.0/token HTTP/1.1           
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id={CLIENT_APPLICATION_ID}
&scope={RESOURCE_APPLICATION_ID}/.default
&client_secret={CLIENT_APPLICATION_SECRET}
&grant_type=client_credentials

ตัวอย่างการยิง request เพื่อ get access token

ขั้นตอนสุดท้ายกลับไปยิง Request หา localhost:8080/azuread ใหม่แต่คราวนี้แนบ Bearer Token ไปกับ Authorization Header ด้วยจะเห็นได้ว่าคราวนี้ Response Status กลับมาเป็น 200 OK พร้อม Response Body

What does this mean?

การที่เราแนบ Bear Token ไปกับ request เพื่อให้ทางฝั่ง Web Service นั้นตรวจสอบว่าเราคือคนที่มันรู้จักมั้ยหรือก็คือเป็น part ของการยืนยันตัวตน (Authentication) นั่นเอง

Source Code

Link: https://github.com/NonTechCompany/spring-oauth2-azuread

Contact

Email: chan.suttichujit@gmail.com

GitHub: https://github.com/NonTechCompany

Credit

https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow

Next Episode

Working with Azure Episode 1: Secure your Spring boot application with Oauth2 + Azure Active Directory (Part 2: Authorization)

--

--