ความปลอดภัยเป็นศัตรูของความสะดวกสบายและในทางกลับกัน คำสั่งนี้เป็นจริงสำหรับระบบใด ๆ ทั้งเสมือนหรือจริงตั้งแต่ทางเข้าบ้านจริงไปจนถึงแพลตฟอร์มเว็บธนาคาร วิศวกรพยายามหาจุดสมดุลที่เหมาะสมสำหรับกรณีการใช้งานที่กำหนดอยู่ตลอดเวลาโดยเอนเอียงไปด้านใดด้านหนึ่ง โดยปกติเมื่อภัยคุกคามใหม่ปรากฏขึ้นเราจะมุ่งไปสู่ความปลอดภัยและไม่สะดวก จากนั้นเราจะดูว่าเราสามารถกู้คืนความสะดวกสบายที่หายไปได้หรือไม่โดยไม่ลดความปลอดภัยมากเกินไป ยิ่งไปกว่านั้นวงจรอุบาทว์นี้ยังคงอยู่ตลอดไป
ลองตรวจสอบสถานะของการรักษาความปลอดภัย REST ในวันนี้โดยใช้บทช่วยสอนเกี่ยวกับความปลอดภัยของ Spring ที่ตรงไปตรงมาเพื่อสาธิตการใช้งาน
บริการ REST (ซึ่งย่อมาจาก Representational State Transfer) เริ่มต้นจากวิธีการที่ง่ายมากสำหรับ Web Services ที่มีข้อกำหนดขนาดใหญ่และรูปแบบที่ยุ่งยากเช่น WSDL สำหรับอธิบายบริการหรือ สบู่ สำหรับระบุรูปแบบข้อความ ใน REST เราไม่มีสิ่งเหล่านี้ เราสามารถอธิบายบริการ REST ในไฟล์ข้อความธรรมดาและใช้รูปแบบข้อความที่เราต้องการเช่น JSON, XML หรือแม้แต่ข้อความธรรมดาอีกครั้ง แนวทางที่เรียบง่ายถูกนำไปใช้กับความปลอดภัยของบริการ REST ด้วยเช่นกัน ไม่มีมาตรฐานที่กำหนดไว้กำหนดวิธีการตรวจสอบผู้ใช้โดยเฉพาะ
แม้ว่าบริการ REST จะไม่ได้ระบุไว้มาก แต่สิ่งที่สำคัญคือการขาดสถานะ หมายความว่าเซิร์ฟเวอร์ไม่เก็บสถานะไคลเอ็นต์ใด ๆ โดยมีเซสชันเป็นตัวอย่างที่ดี ดังนั้นเซิร์ฟเวอร์ตอบกลับคำขอแต่ละรายการราวกับว่าเป็นครั้งแรกที่ไคลเอ็นต์ทำ อย่างไรก็ตามแม้ในปัจจุบันการใช้งานจำนวนมากยังคงใช้การรับรองความถูกต้องตามคุกกี้ซึ่งสืบทอดมาจากการออกแบบสถาปัตยกรรมเว็บไซต์มาตรฐาน วิธีการแบบไร้สัญชาติของ REST ทำให้คุกกี้เซสชันไม่เหมาะสมจากจุดยืนด้านความปลอดภัย แต่อย่างไรก็ตามยังคงใช้กันอย่างแพร่หลาย นอกเหนือจากการเพิกเฉยต่อความไร้สัญชาติที่ต้องการแล้วแนวทางที่เรียบง่ายยังมาพร้อมกับการแลกเปลี่ยนความปลอดภัยที่คาดไว้ เมื่อเทียบกับมาตรฐาน WS-Security ที่ใช้สำหรับ Web Services การสร้างและใช้บริการ REST นั้นง่ายกว่ามากดังนั้นความสะดวกสบายจึงผ่านหลังคา การแลกเปลี่ยนมีความปลอดภัยค่อนข้างน้อย การจี้เซสชันและการปลอมแปลงคำขอข้ามไซต์ (XSRF) เป็นปัญหาด้านความปลอดภัยที่พบบ่อยที่สุด
ในการพยายามกำจัดเซสชันไคลเอ็นต์ออกจากเซิร์ฟเวอร์มีการใช้วิธีการอื่น ๆ เป็นครั้งคราวเช่นการตรวจสอบสิทธิ์ HTTP ขั้นพื้นฐานหรือไดเจสต์ ทั้งสองใช้ Authorization
ส่วนหัวเพื่อส่งข้อมูลรับรองผู้ใช้โดยเพิ่มการเข้ารหัส (HTTP Basic) หรือการเข้ารหัส (HTTP Digest) แน่นอนว่าพวกเขามีข้อบกพร่องเดียวกันกับที่พบในเว็บไซต์: ต้องใช้ HTTP Basic ผ่าน HTTPS เนื่องจากชื่อผู้ใช้และรหัสผ่านถูกส่งในการเข้ารหัส base64 ที่ย้อนกลับได้อย่างง่ายดายและ HTTP Digest บังคับให้ใช้การแฮช MD5 ที่ล้าสมัยซึ่งพิสูจน์แล้วว่าไม่ปลอดภัย
ในที่สุดการใช้งานบางอย่างก็ใช้โทเค็นโดยพลการเพื่อพิสูจน์ตัวตนลูกค้า ตัวเลือกนี้ดูเหมือนจะดีที่สุดที่เรามีในตอนนี้ หากใช้งานอย่างถูกต้องจะแก้ไขปัญหาด้านความปลอดภัยทั้งหมดของ HTTP Basic, HTTP Digest หรือคุกกี้เซสชันใช้งานง่ายและเป็นไปตามรูปแบบที่ไม่มีสถานะ
อย่างไรก็ตามด้วยโทเค็นตามอำเภอใจดังกล่าวจึงมีมาตรฐานเล็กน้อยที่เกี่ยวข้อง ผู้ให้บริการทุกรายมีความคิดว่าจะใส่อะไรลงในโทเค็นและจะเข้ารหัสหรือเข้ารหัสอย่างไร การใช้บริการจากผู้ให้บริการที่แตกต่างกันจำเป็นต้องใช้เวลาในการตั้งค่าเพิ่มเติมเพื่อปรับให้เข้ากับรูปแบบโทเค็นเฉพาะที่ใช้ ในทางกลับกันวิธีการอื่น ๆ (คุกกี้เซสชัน, HTTP Basic และ HTTP Digest) เป็นที่รู้จักกันดีสำหรับนักพัฒนาและเบราว์เซอร์เกือบทั้งหมดบนอุปกรณ์ทั้งหมดสามารถใช้งานได้ทันที เฟรมเวิร์กและภาษาพร้อมสำหรับวิธีการเหล่านี้โดยมีฟังก์ชันในตัวเพื่อจัดการกับแต่ละส่วนอย่างราบรื่น
JWT (ย่อมาจาก JSON Web Token) คือมาตรฐานที่ขาดหายไปสำหรับการใช้โทเค็นเพื่อพิสูจน์ตัวตนบนเว็บโดยทั่วไปไม่ใช่เฉพาะสำหรับบริการ REST ขณะนี้อยู่ในสถานะร่างเป็น RFC 7519 . มีความแข็งแรงและสามารถรับข้อมูลได้มาก แต่ก็ยังใช้งานง่ายแม้ว่าขนาดจะค่อนข้างเล็กก็ตาม เช่นเดียวกับโทเค็นอื่น ๆ JWT สามารถใช้เพื่อส่งผ่านข้อมูลประจำตัวของผู้ใช้ที่ได้รับการพิสูจน์ตัวตนระหว่างผู้ให้บริการข้อมูลประจำตัวและผู้ให้บริการ (ซึ่งไม่จำเป็นต้องเป็นระบบเดียวกัน) นอกจากนี้ยังสามารถดำเนินการอ้างสิทธิ์ทั้งหมดของผู้ใช้เช่นข้อมูลการให้สิทธิ์ดังนั้นผู้ให้บริการจึงไม่จำเป็นต้องเข้าไปในฐานข้อมูลหรือระบบภายนอกเพื่อตรวจสอบบทบาทและสิทธิ์ของผู้ใช้สำหรับแต่ละคำขอ ข้อมูลนั้นถูกดึงออกจากโทเค็น
นี่คือวิธีการออกแบบความปลอดภัยของ JWT:
Authorization
ส่วนหัวและถอดรหัสหากจำเป็นตรวจสอบลายเซ็นและหากทุกอย่างเรียบร้อยให้แยกข้อมูลผู้ใช้และสิทธิ์ จากข้อมูลนี้เพียงอย่างเดียวและอีกครั้งโดยไม่ต้องค้นหารายละเอียดเพิ่มเติมในฐานข้อมูลหรือติดต่อผู้ให้บริการข้อมูลประจำตัวก็สามารถยอมรับหรือปฏิเสธคำขอของลูกค้าได้ ข้อกำหนดเพียงอย่างเดียวคือข้อมูลประจำตัวและผู้ให้บริการต้องมีข้อตกลงในการเข้ารหัสเพื่อให้บริการสามารถตรวจสอบลายเซ็นหรือแม้แต่ถอดรหัสข้อมูลประจำตัวที่ถูกเข้ารหัสขั้นตอนนี้ช่วยให้เกิดความยืดหยุ่นอย่างมากในขณะที่ยังคงรักษาความปลอดภัยและพัฒนาได้ง่าย การใช้วิธีนี้ทำให้ง่ายต่อการเพิ่มโหนดเซิร์ฟเวอร์ใหม่ให้กับคลัสเตอร์ผู้ให้บริการโดยเริ่มต้นด้วยความสามารถในการตรวจสอบลายเซ็นและถอดรหัสโทเค็นโดยให้คีย์ลับที่ใช้ร่วมกันเท่านั้น ไม่จำเป็นต้องมีการจำลองแบบเซสชันการซิงโครไนซ์ฐานข้อมูลหรือการสื่อสารระหว่างโหนด พักผ่อนอย่างเต็มเปี่ยม
ความแตกต่างที่สำคัญระหว่าง JWT และโทเค็นอื่น ๆ โดยพลการคือการกำหนดมาตรฐานของเนื้อหาของโทเค็น อีกวิธีหนึ่งที่แนะนำคือการส่งโทเค็น JWT ใน Authorization
ส่วนหัวโดยใช้โครงการ Bearer เนื้อหาของส่วนหัวควรมีลักษณะดังนี้:
วิธีเขียนภาษาโปรแกรม
Authorization: Bearer
เพื่อให้บริการ REST ทำงานได้ตามที่คาดไว้เราจำเป็นต้องใช้วิธีการอนุญาตที่แตกต่างกันเล็กน้อยเมื่อเทียบกับเว็บไซต์แบบหลายหน้าแบบคลาสสิก
แทนที่จะทริกเกอร์กระบวนการพิสูจน์ตัวตนโดยเปลี่ยนเส้นทางไปยังเพจล็อกอินเมื่อไคลเอ็นต์ร้องขอทรัพยากรที่ปลอดภัยเซิร์ฟเวอร์ REST จะพิสูจน์ตัวตนคำขอทั้งหมดโดยใช้ข้อมูลที่มีอยู่ในคำร้องขอโทเค็น JWT ในกรณีนี้ หากการตรวจสอบสิทธิ์ดังกล่าวล้มเหลวการเปลี่ยนเส้นทางก็ไม่สมเหตุสมผล REST API เพียงแค่ส่งการตอบสนองรหัส HTTP 401 (ไม่ได้รับอนุญาต) และลูกค้าควรรู้ว่าต้องทำอย่างไร ตัวอย่างเช่นเบราว์เซอร์จะแสดง div แบบไดนามิกเพื่อให้ผู้ใช้ระบุชื่อผู้ใช้และรหัสผ่าน
ในทางกลับกันหลังจากการรับรองความถูกต้องสำเร็จในเว็บไซต์หลายหน้าแบบคลาสสิกผู้ใช้จะถูกเปลี่ยนเส้นทางโดยใช้รหัส HTTP 301 (ย้ายถาวร) โดยปกติจะไปที่โฮมเพจหรือที่ดีกว่านั้นคือไปยังหน้าที่ผู้ใช้ร้องขอในตอนแรกที่ทริกเกอร์ กระบวนการรับรองความถูกต้อง ด้วย REST อีกครั้งสิ่งนี้ไม่สมเหตุสมผล แต่เราจะดำเนินการตามคำขอต่อไปราวกับว่าทรัพยากรไม่ได้รับความปลอดภัยเลยให้ส่งคืนรหัส HTTP 200 (ตกลง) และเนื้อหาตอบกลับที่คาดไว้
ตอนนี้เรามาดูกันว่าเราจะใช้ REST API ที่ใช้โทเค็น JWT ได้อย่างไรโดยใช้ Java และ ฤดูใบไม้ผลิ ในขณะที่พยายามใช้พฤติกรรมเริ่มต้น Spring Security ซ้ำในที่ที่เราทำได้
ตามที่คาดไว้ Spring Security framework มาพร้อมกับคลาสปลั๊กอินที่พร้อมใช้งานจำนวนมากที่จัดการกับกลไกการอนุญาต 'เก่า' ได้แก่ คุกกี้เซสชัน HTTP Basic และ HTTP Digest อย่างไรก็ตามมันขาดการสนับสนุนดั้งเดิมสำหรับ JWT และเราจำเป็นต้องทำให้มือของเราสกปรกเพื่อให้มันใช้งานได้ สำหรับภาพรวมโดยละเอียดเพิ่มเติมคุณควรปรึกษาอย่างเป็นทางการ เอกสาร Spring Security .
มาเริ่มกันเลยตามปกติ นิยามตัวกรอง Spring Security ใน web.xml
:
springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy springSecurityFilterChain /*
โปรดทราบว่าชื่อของตัวกรอง Spring Security ต้องตรงกับ springSecurityFilterChain
สำหรับส่วนที่เหลือของการกำหนดค่า Spring จะทำงานนอกกรอบ
ต่อไปคือการประกาศ XML ของถั่วสปริงที่เกี่ยวข้องกับความปลอดภัย เพื่อให้ XML ง่ายขึ้นเราจะตั้งค่าเนมสเปซเริ่มต้นเป็น security
โดยเพิ่ม xmlns='http://www.springframework.org/schema/security'
ไปยังองค์ประกอบราก XML XML ที่เหลือมีลักษณะดังนี้:
(1) (2) (3) (4) (5) (6) (7) (8)
@PreFilter
, @PreAuthorize
, @PostFilter
, @PostAuthorize
คำอธิบายประกอบเกี่ยวกับถั่วสปริงในบริบทstateless
(เราไม่ต้องการให้เซสชันสร้างขึ้นเพื่อจุดประสงค์ด้านความปลอดภัยเนื่องจากเราใช้โทเค็นสำหรับแต่ละคำขอ)csrf
การป้องกันเนื่องจากโทเค็นของเรามีภูมิคุ้มกันต่อมันAbstractAuthenticationProcessingFilter
ของ Spring เราจึงจำเป็นต้องประกาศใน XML เพื่อเชื่อมต่อคุณสมบัติของมัน (การต่อสายอัตโนมัติไม่ทำงานที่นี่) เราจะอธิบายในภายหลังว่าตัวกรองทำอะไรAbstractAuthenticationProcessingFilter
ไม่ดีพอสำหรับวัตถุประสงค์ REST เนื่องจากเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าความสำเร็จ นั่นคือเหตุผลที่เราตั้งค่าของเราเองที่นี่authenticationManager
ถูกใช้โดยตัวกรองของเราเพื่อตรวจสอบสิทธิ์ผู้ใช้ตอนนี้เรามาดูกันว่าเราใช้คลาสเฉพาะที่ประกาศใน XML ด้านบนอย่างไร โปรดทราบว่า Spring จะต่อสายให้เรา เราเริ่มต้นด้วยสิ่งที่ง่ายที่สุด
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { // This is invoked when user tries to access a secured REST resource without supplying any credentials // We should just send a 401 Unauthorized response because there is no 'login page' to redirect to response.sendError(HttpServletResponse.SC_UNAUTHORIZED, 'Unauthorized'); } }
ตามที่อธิบายไว้ข้างต้นคลาสนี้จะส่งคืนรหัส HTTP 401 (ไม่ได้รับอนุญาต) เมื่อการตรวจสอบความถูกต้องล้มเหลวซึ่งจะลบล้างการเปลี่ยนเส้นทางเริ่มต้นของ Spring
public class JwtAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { // We do not need to do anything extra on REST authentication success, because there is no page to redirect to } }
การแทนที่อย่างง่ายนี้จะลบพฤติกรรมเริ่มต้นของการพิสูจน์ตัวตนที่ประสบความสำเร็จ (เปลี่ยนเส้นทางไปที่บ้านหรือหน้าอื่น ๆ ที่ผู้ใช้ร้องขอ) หากคุณสงสัยว่าทำไมเราไม่จำเป็นต้องลบล้าง AuthenticationFailureHandler
นั่นเป็นเพราะการใช้งานเริ่มต้นจะไม่เปลี่ยนเส้นทางไปที่ใดก็ได้หากไม่ได้ตั้งค่า URL เปลี่ยนเส้นทางดังนั้นเราจึงหลีกเลี่ยงการตั้งค่า URL ซึ่งดีพอ
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public JwtAuthenticationFilter() { super('/**'); } @Override protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) { return true; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { String header = request.getHeader('Authorization'); if (header == null || !header.startsWith('Bearer ')) { throw new JwtTokenMissingException('No JWT token found in request headers'); } String authToken = header.substring(7); JwtAuthenticationToken authRequest = new JwtAuthenticationToken(authToken); return getAuthenticationManager().authenticate(authRequest); } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { super.successfulAuthentication(request, response, chain, authResult); // As this authentication is in HTTP header, after success we need to continue the request normally // and return the response as if the resource was not secured at all chain.doFilter(request, response); } }
คลาสนี้เป็นจุดเริ่มต้นของกระบวนการรับรองความถูกต้อง JWT ของเรา ตัวกรองจะแยกโทเค็น JWT ออกจากส่วนหัวของคำร้องขอและมอบหมายการพิสูจน์ตัวตนให้กับการแทรก AuthenticationManager
หากไม่พบโทเค็นจะมีข้อยกเว้นที่หยุดการร้องขอจากการประมวลผล นอกจากนี้เรายังต้องการการแทนที่เพื่อให้การตรวจสอบสิทธิ์สำเร็จเนื่องจากการไหลของ Spring เริ่มต้นจะหยุดห่วงโซ่ตัวกรองและดำเนินการเปลี่ยนเส้นทาง โปรดทราบว่าเราจำเป็นต้องใช้สายโซ่เพื่อดำเนินการอย่างเต็มที่รวมถึงการสร้างการตอบสนองตามที่อธิบายไว้ข้างต้น
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { @Autowired private JwtUtil jwtUtil; @Override public boolean supports(Class authentication) { return (JwtAuthenticationToken.class.isAssignableFrom(authentication)); } @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { } @Override protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication; String token = jwtAuthenticationToken.getToken(); User parsedUser = jwtUtil.parseToken(token); if (parsedUser == null) { throw new JwtTokenMalformedException('JWT token is not valid'); } List authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(parsedUser.getRole()); return new AuthenticatedUser(parsedUser.getId(), parsedUser.getUsername(), token, authorityList); } }
ในคลาสนี้เราใช้ Spring’s default AuthenticationManager
แต่เราฉีดด้วย AuthenticationProvider
ของเราเอง นั่นคือกระบวนการรับรองความถูกต้องที่แท้จริง ในการดำเนินการนี้เราขยาย AbstractUserDetailsAuthenticationProvider
ซึ่งต้องการให้เราส่งคืน UserDetails
เท่านั้น ตามคำขอการตรวจสอบสิทธิ์ในกรณีของเราโทเค็น JWT ที่รวมอยู่ใน JwtAuthenticationToken
ชั้นเรียน. หากโทเค็นไม่ถูกต้องเราจะให้ข้อยกเว้น อย่างไรก็ตามหากถูกต้องและถอดรหัสโดย JwtUtil
ประสบความสำเร็จเราแยกรายละเอียดผู้ใช้ (เราจะเห็นว่าในคลาส JwtUtil
) โดยไม่ต้องเข้าถึงฐานข้อมูลเลย ข้อมูลทั้งหมดเกี่ยวกับผู้ใช้รวมถึงบทบาทของผู้ใช้จะอยู่ในโทเค็นนั้นเอง
วิธีสร้างเว็บไซต์ด้วย angularjs
public class JwtUtil { @Value('${jwt.secret}') private String secret; /** * Tries to parse specified String as a JWT token. If successful, returns User object with username, id and role prefilled (extracted from token). * If unsuccessful (token is invalid or not containing all required user properties), simply returns null. * * @param token the JWT token to parse * @return the User object extracted from specified token or null if a token is invalid. */ public User parseToken(String token) { try { Claims body = Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); User u = new User(); u.setUsername(body.getSubject()); u.setId(Long.parseLong((String) body.get('userId'))); u.setRole((String) body.get('role')); return u; } catch (JwtException | ClassCastException e) { return null; } } /** * Generates a JWT token containing username as subject, and userId and role as additional claims. These properties are taken from the specified * User object. Tokens validity is infinite. * * @param u the user for which the token will be generated * @return the JWT token */ public String generateToken(User u) { Claims claims = Jwts.claims().setSubject(u.getUsername()); claims.put('userId', u.getId() + ''); claims.put('role', u.getRole()); return Jwts.builder() .setClaims(claims) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } }
สุดท้าย JwtUtil
คลาสมีหน้าที่แยกวิเคราะห์โทเค็นเป็น User
วัตถุและสร้างโทเค็นจาก User
วัตถุ. ตรงไปตรงมาเนื่องจากใช้ไฟล์ jjwt
ห้องสมุด เพื่อทำงานทั้งหมดของ JWT ในตัวอย่างของเราเราเพียงแค่เก็บชื่อผู้ใช้ ID ผู้ใช้และบทบาทของผู้ใช้ไว้ในโทเค็น นอกจากนี้เรายังสามารถจัดเก็บสิ่งของต่างๆได้ตามอำเภอใจและเพิ่มคุณสมบัติด้านความปลอดภัยอื่น ๆ เช่นการหมดอายุของโทเค็น การแยกวิเคราะห์โทเค็นใช้ใน AuthenticationProvider
ดังที่แสดงไว้ด้านบน generateToken()
เมธอดถูกเรียกใช้จากบริการ REST เข้าสู่ระบบและสมัครใช้งานซึ่งไม่ปลอดภัยและจะไม่ทริกเกอร์การตรวจสอบความปลอดภัยใด ๆ หรือต้องมีโทเค็นในคำขอ ในท้ายที่สุดมันจะสร้างโทเค็นที่จะถูกส่งกลับไปยังไคลเอนต์ตามผู้ใช้
แม้ว่าวิธีการรักษาความปลอดภัยแบบเก่าที่เป็นมาตรฐาน (คุกกี้เซสชัน, HTTP Basic และ HTTP Digest) จะทำงานร่วมกับบริการ REST ได้เช่นกัน แต่ก็มีปัญหาที่ควรหลีกเลี่ยงโดยใช้มาตรฐานที่ดีกว่า JWT มาถึงทันเวลาเพื่อช่วยวันและที่สำคัญที่สุดใกล้จะกลายเป็นมาตรฐาน IETF แล้ว
จุดแข็งหลักของ JWT คือการจัดการการตรวจสอบผู้ใช้แบบไร้สถานะดังนั้นจึงสามารถปรับขนาดได้ในขณะเดียวกันก็รักษาความปลอดภัยด้วยมาตรฐานการเข้ารหัสที่ทันสมัย การจัดเก็บการอ้างสิทธิ์ (บทบาทของผู้ใช้และสิทธิ์) ในโทเค็นนั้นสร้างประโยชน์อย่างมากในสถาปัตยกรรมระบบแบบกระจายซึ่งเซิร์ฟเวอร์ที่ส่งคำขอไม่มีสิทธิ์เข้าถึงแหล่งข้อมูลการพิสูจน์ตัวตน
REST ย่อมาจาก Representational State Transfer เป็นรูปแบบสถาปัตยกรรมสำหรับการเปิดเผย API ที่สอดคล้องกันระหว่างบริการบนเว็บ
JSON Web Token (JWT) เป็นมาตรฐานสำหรับการเข้ารหัสข้อมูลที่อาจถูกส่งอย่างปลอดภัยเป็นออบเจ็กต์ JSON