คำถามติดแท็ก oauth-2.0

OAuth (Open Authorization) เป็นเฟรมเวิร์กโปรโตคอลแบบเปิดที่อนุญาตการอนุญาต API ที่ปลอดภัยด้วยวิธีที่ง่ายและได้มาตรฐานสำหรับแอปพลิเคชันเดสก์ท็อปอุปกรณ์เคลื่อนที่และเว็บ OAuth 2.0 เป็นโปรโตคอล OAuth เวอร์ชันที่สอง

3
โฟลว์โทเค็นการรีเฟรช JWT
ฉันกำลังสร้างแอพมือถือและกำลังใช้ JWT สำหรับการพิสูจน์ตัวตน ดูเหมือนว่าวิธีที่ดีที่สุดในการทำเช่นนี้คือการจับคู่โทเค็นการเข้าถึง JWT กับโทเค็นการรีเฟรชเพื่อให้ฉันสามารถหมดอายุโทเค็นการเข้าถึงได้บ่อยเท่าที่ฉันต้องการ โทเค็นการรีเฟรชมีลักษณะอย่างไร มันเป็นสตริงสุ่มหรือไม่? สตริงนั้นเข้ารหัสหรือไม่ เป็น JWT อื่นหรือไม่? โทเค็นการรีเฟรชจะถูกเก็บไว้ในฐานข้อมูลบนโมเดลผู้ใช้สำหรับการเข้าถึงถูกต้องหรือไม่? ดูเหมือนว่าควรเข้ารหัสในกรณีนี้ ฉันจะส่งโทเค็นการรีเฟรชกลับหลังจากล็อกอินของผู้ใช้แล้วให้ไคลเอนต์เข้าถึงเส้นทางแยกต่างหากเพื่อดึงโทเค็นการเข้าถึงหรือไม่

4
วิธีติดตั้งเซิร์ฟเวอร์ oauth2 ใน ASP.NET MVC 5 และ WEB API 2 [ปิด]
ปิด. คำถามนี้ไม่เป็นไปตามหลักเกณฑ์กองมากเกิน ขณะนี้ยังไม่ยอมรับคำตอบ ต้องการปรับปรุงคำถามนี้หรือไม่? อัปเดตคำถามเพื่อให้เป็นหัวข้อสำหรับ Stack Overflow ปิดให้บริการเมื่อปีที่แล้ว ปรับปรุงคำถามนี้ ก่อนอื่นฉันจะร่างโครงการของฉัน: สำหรับการฝึกงานของฉันฉันต้องเพิ่มฟังก์ชันการทำงานให้กับระบบที่มีอยู่ ไคลเอ็นต์ของบุคคลที่สามต้องสามารถเข้าถึงข้อมูลจาก AX Webservices เมื่อได้รับอนุญาตจากผู้ใช้ผ่าน OAuth2 ฉันเข้าใจว่าฉันจำเป็นต้องสร้าง 'บริการเว็บพร็อกซี' โดยที่ไคลเอนต์สามารถโทรออกและเรียกใช้บริการ AX ได้ แต่ฉันไม่แน่ใจเกี่ยวกับส่วน OAuth2 เล็กน้อย บทแนะนำและคำแนะนำส่วนใหญ่เกี่ยวกับการใช้ข้อมูลประจำตัวของ ASP.NET สำหรับ Facebook หรือ Google-logins ฉันไม่ต้องการสิ่งนั้นฉันต้องใช้ข้อมูลรับรองที่มีอยู่ดังนั้นฉันจึงต้องสร้างบริการ OAuth2 ของฉันเอง ฉันพบว่ามันยากที่จะหาบทเรียนคำแนะนำหรือคำอธิบายเกี่ยวกับเรื่องนี้ ฉันเข้าใจ OAuth2 และสิ่งที่ต้องทำ แต่ฉันไม่เคยทำสิ่งนี้มาก่อนและพบว่ามันยากที่จะเริ่มต้น สิ่งที่ใกล้เคียงที่สุดกับสิ่งที่ฉันต้องการที่ฉันพบคือลิงก์ github repoนี้ แต่โซลูชันไม่ได้สร้างขึ้น สิ่งที่ฉันคิดคือการสร้างเว็บไซต์ ASP.NET MVC ที่ลูกค้า (บุคคลที่สาม) สามารถลงทะเบียนด้วยตนเองและรับรหัสลูกค้าของตนได้ ด้วย ASP.NET …

8
ฉันจะดูรายการขอบเขตสำหรับ OAuth 2.0 API ของ Google ได้ที่ไหน [ปิด]
ปิด. คำถามนี้ไม่เป็นไปตามหลักเกณฑ์กองมากเกิน ขณะนี้ยังไม่ยอมรับคำตอบ ต้องการปรับปรุงคำถามนี้หรือไม่ อัปเดตคำถามเพื่อให้เป็นหัวข้อสำหรับ Stack Overflow ปิดให้บริการใน4 ปีที่แล้ว ปรับปรุงคำถามนี้ ตัวอย่างที่ฉันกำลังดำเนินการระบุขอบเขตในคำขอ OAuth เป็น: scope = https% 3A% 2F% 2Fwww.googleapis.com% 2Fauth% 2Fuserinfo.email + https% 3A% 2F% 2Fwww.googleapis.com% 2Fauth% 2Fuserinfo.profile ซึ่งถอดรหัสเป็นสอง URI: https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile ฉันไม่พบเอกสารที่ครอบคลุมรายการขอบเขตทั้งหมดที่มีอยู่และข้อมูลใดที่สามารถเข้าถึงได้ภายในแต่ละขอบเขตมีใครทราบบ้างว่ามีสิ่งนั้นอยู่หรือไม่?

4
JWT (Json Web Token) "ผู้ชม" กับ Client_Id - ความแตกต่างคืออะไร?
ฉันกำลังดำเนินการติดตั้ง OAuth 2.0 JWT access_token ในเซิร์ฟเวอร์การตรวจสอบสิทธิ์ของฉัน แต่ฉันไม่ชัดเจนว่าความแตกต่างระหว่างการaudอ้างสิทธิ์JWT และclient_idค่าส่วนหัว HTTP คืออะไร พวกเดียวกันหรือเปล่า? ถ้าไม่คุณสามารถอธิบายความแตกต่างระหว่างทั้งสองได้หรือไม่? ความสงสัยของฉันคือaudควรอ้างถึงเซิร์ฟเวอร์ทรัพยากรและclient_idควรอ้างถึงแอปพลิเคชันไคลเอนต์ตัวใดตัวหนึ่งที่เซิร์ฟเวอร์รับรองความถูกต้อง (เช่นเว็บแอปหรือแอป iOS) ในกรณีปัจจุบันเซิร์ฟเวอร์ทรัพยากรของฉันยังเป็นไคลเอนต์เว็บแอปของฉัน
103 oauth  oauth-2.0  jwt 

9
มีตัวอย่าง JSON Web Token (JWT) ใน C # หรือไม่
ฉันรู้สึกเหมือนกำลังกินยาบ้าๆอยู่ที่นี่ โดยปกติแล้วจะมีไลบรารีและตัวอย่างกว่าล้านตัวอย่างลอยอยู่บนเว็บสำหรับงานใด ๆ ก็ตาม ฉันพยายามที่จะใช้การตรวจสอบด้วย Google "บัญชีบริการ" โดยการใช้ JSON เว็บโทเคน (JWT) ตามที่อธิบายไว้ที่นี่ อย่างไรก็ตามมีเฉพาะไลบรารีไคลเอ็นต์ใน PHP, Python และ Java แม้แต่การค้นหาตัวอย่าง JWT นอกการตรวจสอบสิทธิ์ของ Google ก็มีเพียงจิ้งหรีดและร่างแนวคิด JWT นี่เป็นระบบใหม่จริง ๆ และอาจเป็นระบบที่เป็นกรรมสิทธิ์ของ Google หรือไม่ ตัวอย่าง java ที่ใกล้เคียงที่สุดที่ฉันสามารถตีความได้ดูค่อนข้างเข้มข้นและน่ากลัว จะต้องมีบางอย่างใน C # ที่อย่างน้อยฉันก็เริ่มได้ ช่วยด้วยจะดีมาก!
102 c#  oauth  oauth-2.0  jwt 

4
ข้อผิดพลาด: ช่องส่วนหัวของคำขอประเภทเนื้อหาไม่ได้รับอนุญาตโดย Access-Control-Allow-Headers
ฉันสร้างโครงการ mvc4 web api โดยใช้ vS2012 ฉันใช้บทช่วยสอนต่อไปนี้เพื่อแก้ปัญหา Cross-Origin Resource Sharing "http://blogs.msdn.com/b/carlosfigueira/archive/2012/07/02/cors-support-in-asp-net-web-api- rc-version.aspx ". ทำงานได้สำเร็จและฉันโพสต์ข้อมูลจากฝั่งไคลเอ็นต์ไปยังเซิร์ฟเวอร์เรียบร้อยแล้ว หลังจากนั้นสำหรับการใช้ Autherization ในโปรเจ็กต์ของฉันฉันใช้บทช่วยสอนต่อไปนี้เพื่อติดตั้ง OAuth2 "http://community.codesmithtools.com/CodeSmith_Community/b/tdupont/archive/2011/03/18/oauth-2-0-for -mvc- สองขา -plement.aspx " นี่คือความช่วยเหลือฉันในการรับ RequestToken ทางฝั่งไคลเอ็นต์ แต่เมื่อฉันโพสต์ข้อมูลจากฝั่งไคลเอ็นต์ฉันได้รับข้อผิดพลาด "XMLHttpRequest ไม่สามารถโหลด http: // ช่องส่วนหัวของคำขอ Content-Type ไม่ได้รับอนุญาตโดย Access-Control-Allow-Headers" รหัสฝั่งไคลเอ็นต์ของฉันมีลักษณะดังนี้ function PostLogin() { var Emp = {}; Emp.UserName = $("#txtUserName").val(); var pass = $("#txtPassword").val(); …

3
ข้อมูลลับของไคลเอ็นต์ใน OAuth 2.0
ในการใช้ google drive api ฉันต้องเล่นกับการรับรองความถูกต้องโดยใช้ OAuth2.0 และฉันมีคำถามสองสามข้อเกี่ยวกับเรื่องนี้ รหัสลูกค้าและความลับของไคลเอ็นต์ใช้เพื่อระบุว่าแอปของฉันคืออะไร แต่จะต้องเป็นฮาร์ดโค้ดหากเป็นแอปพลิเคชันไคลเอนต์ ดังนั้นทุกคนสามารถถอดรหัสแอปของฉันและแยกออกจากซอร์สโค้ดได้ หมายความว่าแอปที่ไม่ดีสามารถแอบอ้างว่าเป็นแอปที่ดีโดยใช้รหัสไคลเอ็นต์และรหัสลับของแอปที่ดีได้หรือไม่? ดังนั้นผู้ใช้จะแสดงหน้าจอว่าขออนุญาตแอพที่ดีแม้ว่าจะถูกถามโดยแอพที่ไม่ดีจริง ๆ ? ถ้าใช่ฉันควรทำอย่างไร? หรือจริงๆแล้วฉันไม่ควรกังวลเกี่ยวกับเรื่องนี้? ในแอปพลิเคชันมือถือเราสามารถฝังมุมมองเว็บลงในแอปของเราได้ และง่ายต่อการแยกช่องรหัสผ่านใน webview เนื่องจากแอปที่ขออนุญาตเป็น "เบราว์เซอร์" จริงๆ ดังนั้น OAuth ในแอปพลิเคชันมือถือจึงไม่มีประโยชน์ที่แอปพลิเคชันไคลเอนต์ไม่สามารถเข้าถึงข้อมูลรับรองผู้ใช้ของผู้ให้บริการ?

23
ไม่มีผู้ใช้ที่เกี่ยวข้องกับข้อผิดพลาด PG undefinedtable
ฉันเห็นคำถามนี้มาก่อน แต่สำหรับ rspec เท่านั้น ฉันยังไม่ได้สร้างแบบทดสอบเพราะมันล้ำหน้าเกินไปสำหรับฉัน แต่วันหนึ่งในไม่ช้าฉันจะทำ! : ป ฉันได้รับข้อผิดพลาดนี้เมื่อพยายามลงทะเบียน / ล็อกอินเข้าสู่แอปของฉัน ผมใช้ประดิษฐ์เพื่อสร้างผู้ใช้และยังomniauth2ลงชื่อเข้าใช้ด้วยGoogle นี่คือข้อผิดพลาด ActiveRecord::StatementInvalid at /users/auth/google_oauth2/callback PG::UndefinedTable: ERROR: relation "users" does not exist LINE 5: WHERE a.attrelid = '"users"'::regclass ^ : SELECT a.attname, format_type(a.atttypid, a.atttypmod), pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = …

7
เจตนาของเวลาหมดอายุ ID Token ใน OpenID Connect คืออะไร?
ใน OpenID Connect โทเค็นการเข้าถึงมีเวลาหมดอายุ สำหรับโฟลว์รหัสการอนุญาตโดยทั่วไปจะสั้น (เช่น 20 นาที) หลังจากนั้นคุณใช้โทเค็นการรีเฟรชเพื่อขอโทเค็นการเข้าถึงใหม่ ID tokenนอกจากนี้ยังมีเวลาหมดอายุ คำถามของฉันคือเจตนาของสิ่งนี้คืออะไร? เวลาหมดอายุของโทเค็น ID ใด ๆ น้อยกว่าเวลาหมดอายุของโทเค็นการรีเฟรชจะหมายความว่าในที่สุดคุณจะมีโทเค็น ID ที่หมดอายุ แต่โทเค็นการเข้าถึงที่ถูกต้อง คุณตั้งใจที่จะ: กำหนดให้โทเค็นรหัสของคุณหมดอายุนานกว่าการหมดอายุโทเค็นการรีเฟรชหรือ ตั้งค่าให้หมดอายุเช่นเดียวกับโทเค็นการเข้าถึงและดำเนินการบางอย่าง (อะไรนะ?) เมื่อหมดอายุหรือ เพียงแค่ใช้โทเค็น ID ในไคลเอนต์ของคุณในใบเสร็จรับเงินจากนั้นละเว้นเวลาหมดอายุหลังจากนั้น? ข้อกำหนดOpenID Connectบอกว่าเมื่อตรวจสอบความถูกต้องของโทเค็น ID "The current time MUST be before the time represented by the exp Claim." ซึ่ง (อาจ) รองรับตัวเลือกที่สามด้านบน แก้ไข เนื่องจาก OpenID …

17
จะรีเฟรชโทเค็นด้วยไคลเอนต์ Google API ได้อย่างไร
ฉันได้เล่นกับ Google Analytics API (V3) และพบข้อผิดพลาดบางอย่าง ประการแรกทุกอย่างตั้งค่าถูกต้องและทำงานร่วมกับบัญชีทดสอบของฉัน แต่เมื่อฉันต้องการดึงข้อมูลจากรหัสโปรไฟล์อื่น (บัญชี Google Accont / GA เดียวกัน) ฉันได้รับข้อผิดพลาด 403 สิ่งที่แปลกคือข้อมูลจากบัญชี GA บางบัญชีจะส่งคืนข้อมูลในขณะที่อีกบัญชีสร้างข้อผิดพลาดนี้ ฉันได้เพิกถอนโทเค็นและตรวจสอบสิทธิ์อีกครั้งและตอนนี้ดูเหมือนว่าฉันสามารถดึงข้อมูลจากบัญชีทั้งหมดของฉันได้ แก้ไขปัญหา? ไม่. เนื่องจากคีย์การเข้าถึงจะหมดอายุฉันจะพบปัญหาเดิมอีกครั้ง หากฉันเข้าใจสิ่งต่างๆถูกต้องเราสามารถใช้ resfreshToken เพื่อรับการรับรองความถูกต้องใหม่ได้ ปัญหาคือเมื่อฉันเรียกใช้: $client->refreshToken(refresh_token_key) ข้อผิดพลาดต่อไปนี้จะถูกส่งกลับ: Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }' ฉันได้ตรวจสอบโค้ดหลังเมธอด refreshToken และติดตามคำขอกลับไปที่ไฟล์“ apiOAuth2.php” พารามิเตอร์ทั้งหมดถูกส่งอย่างถูกต้อง Grant_type ถูกเข้ารหัสอย่างหนักเป็น 'refresh_token' ภายในวิธีการดังนั้นจึงยากสำหรับฉันที่จะเข้าใจว่ามีอะไรผิดพลาด อาร์เรย์พารามิเตอร์มีลักษณะดังนี้: …

2
ส่วนหัวการให้สิทธิ์ OAuth 2.0
ฉันต้องการพัฒนา SDK ที่ห่อหุ้มฟังก์ชัน OAuth 2.0 ฉันได้ตรวจสอบความแตกต่างระหว่าง OAuth 1.0 และ 2.0 แล้วและฉันมีความสับสนเกี่ยวกับ Authorization Header ( 1.0และ 2.0 ) พารามิเตอร์โปรโตคอล OAuth 1.0 สามารถส่งโดยใช้ส่วนหัว "การอนุญาต" ของ HTTP แต่ฉันไม่พบสิ่งนี้ที่อธิบายไว้ในปัจจุบัน OAuth 2.0 แบบร่าง OAuth 2.0 รองรับส่วนหัวการให้สิทธิ์หรือไม่ ใน OAuth 1.0 ส่วนหัวของคุณจะมีลักษณะดังนี้: Authorization: OAuth realm="Example", oauth_consumer_key="0685bd9184jfhq22", oauth_token="ad180jjd733klru7", oauth_signature_method="HMAC-SHA1", oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D", oauth_timestamp="137131200", oauth_nonce="4572616e48616d6d65724c61686176", oauth_version="1.0"
91 http  oauth-2.0 

5
จำกัด อีเมลสำหรับเข้าสู่ระบบด้วย Google OAuth2.0 เฉพาะโดเมนเนม
ดูเหมือนว่าฉันไม่พบเอกสารเกี่ยวกับวิธี จำกัด การเข้าสู่ระบบสำหรับเว็บแอปพลิเคชันของฉัน (ซึ่งใช้ OAuth2.0 และ Google APIs) เพื่อยอมรับเฉพาะคำขอการตรวจสอบสิทธิ์จากผู้ใช้ที่มีอีเมลในชื่อโดเมนหรือชุดชื่อโดเมนที่เจาะจง ฉันต้องการอนุญาตพิเศษตรงข้ามกับบัญชีดำ ใครมีคำแนะนำเกี่ยวกับวิธีการทำเอกสารเกี่ยวกับวิธีการที่ได้รับการยอมรับอย่างเป็นทางการหรือวิธีแก้ปัญหาที่ง่ายและปลอดภัย สำหรับบันทึกนี้ฉันไม่ทราบข้อมูลใด ๆ เกี่ยวกับผู้ใช้จนกว่าพวกเขาจะพยายามเข้าสู่ระบบผ่านการตรวจสอบสิทธิ์ OAuth ของ Google สิ่งที่ฉันได้รับกลับมาคือข้อมูลผู้ใช้พื้นฐานและอีเมล

1
OAuth Authorization vs Authentication
คำศัพท์ OAuth รบกวนฉันมานานแล้ว การให้สิทธิ์ OAuth เป็นไปตามที่บางคนแนะนำหรือเป็นการตรวจสอบสิทธิ์ แก้ไขฉันหากฉันผิด แต่ฉันอ่านการอนุญาตมาโดยตลอดว่าเป็นการอนุญาตให้บุคคลอื่นเข้าถึงทรัพยากร แต่ OAuth ดูเหมือนจะไม่มีการใช้งานใด ๆ ที่ช่วยให้ผู้ใช้เข้าถึงทรัพยากรที่กำหนดได้ การใช้งาน OAuth ทั้งหมดที่พูดถึงคือการให้โทเค็นแก่ผู้ใช้ (ลงนามและเข้ารหัสบางครั้ง) จากนั้นโทเค็นนี้จะถูกส่งไปพร้อมกับการเรียกทุกครั้งไปยังจุดสิ้นสุดของบริการส่วนหลังซึ่งมีการตรวจสอบความถูกต้องอีกครั้งไม่ใช่ข้อกังวลเกี่ยวกับ OAuth การตรวจสอบสิทธิ์ OAuth คืออะไร (ทุกบทความบอกว่าไม่ใช่) ซึ่งฉันใช้มันต้องการให้ผู้ใช้ระบุข้อมูลรับรองซึ่งจะพิสูจน์ได้ว่าผู้ใช้ควร / ไม่ควรมีสิทธิ์เข้าถึงหรือไม่ ดังนั้นดูเหมือนว่า OAuth ไม่ใช่ Authorization NOR Authentication เนื่องจากสิ่งเหล่านี้ต้องดำเนินการโดยกระบวนการอื่น แล้วห่ามันคืออะไร? เป็นกระบวนการในการสื่อสารโทเค็นหรือไม่? เป็นคำปุยที่ไม่มีความหมายเฉพาะหรือไม่? เป็นเรื่องยากที่จะถามคำถามเกี่ยวกับเรื่องนี้โดยไม่ฟังดูลึกลับและเชื่อโชคลาง (ผีและก็อบลิน) ดังนั้นฉันคาดหวังว่าการตอบคำถามนี้จะไม่ใช่เรื่องง่ายเช่นกัน ยอมรับความเสี่ยงของคุณเอง
90 oauth  oauth-2.0 

5
ขั้นตอน OAuth 2.0 ที่เหมาะสมสำหรับแอปบนอุปกรณ์เคลื่อนที่คืออะไร
ฉันพยายามใช้การให้สิทธิ์ที่ได้รับมอบหมายใน Web API สำหรับแอปบนอุปกรณ์เคลื่อนที่โดยใช้ OAuth 2.0 ตามข้อกำหนดขั้นตอนการให้สิทธิ์โดยนัยไม่สนับสนุนโทเค็นการรีเฟรชซึ่งหมายความว่าเมื่อมีการให้โทเค็นการเข้าถึงในช่วงเวลาหนึ่งผู้ใช้จะต้องให้สิทธิ์แก่แอปอีกครั้งเมื่อโทเค็นหมดอายุหรือถูกเพิกถอน ฉันเดาว่านี่เป็นสถานการณ์ที่ดีสำหรับโค้ดจาวาสคริปต์ที่ทำงานบนเบราว์เซอร์ตามที่ระบุไว้ในข้อกำหนด ฉันพยายามลดเวลาที่ผู้ใช้ต้องให้สิทธิ์แก่แอปเพื่อรับโทเค็นดังนั้นดูเหมือนว่าขั้นตอนรหัสการอนุญาตจะเป็นตัวเลือกที่ดีเนื่องจากรองรับโทเค็นการรีเฟรช อย่างไรก็ตามขั้นตอนนี้ดูเหมือนจะต้องอาศัยเว็บเบราว์เซอร์เป็นอย่างมากในการดำเนินการเปลี่ยนเส้นทาง ฉันสงสัยว่าขั้นตอนนี้ยังคงเป็นตัวเลือกที่ดีสำหรับแอปบนอุปกรณ์เคลื่อนที่หรือไม่หากใช้เว็บเบราว์เซอร์ในตัว หรือควรไปตามกระแสโดยปริยาย?

11
จะออกจากระบบแอปพลิเคชันที่ฉันใช้ OAuth2 เพื่อเข้าสู่ระบบด้วย Google ได้อย่างไร
ในแอปพลิเคชันของฉันฉันใช้การลงชื่อเข้าใช้ Google โดยใช้ jsapi ฉันใช้ URL https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=xxxxxxเพื่อเชื่อมต่อกับ Google จากนั้นhttps://www.googleapis.com/plus/v1/people/xxxxxxเพื่อรับข้อมูลผู้ใช้ จากโปรไฟล์ Google ตอนนี้ฉันต้องออกจากระบบผู้ใช้จาก Google ในขณะที่คลิกปุ่มจากแอปพลิเคชันของฉัน ฉันจะใช้สิ่งนี้ใน JavaScript ได้อย่างไรหรืออย่างน้อยก็ต้องถามหน้าการเข้าสู่ระบบของ Google ทุกครั้งที่ผู้ใช้ลงชื่อเข้าใช้ ฉันลองapproval_prompt=forceแล้ว แต่ดูเหมือนจะไม่ได้ผล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.