рдЗрд╕ рдЖрд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдмрд╛рд╣рд░реА рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ (рдмрд┐рдЯрдмрдХреЗрдЯ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) OAuth2 рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдкрд░ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЕрдзрд┐рдХреГрдд рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗредрд╣рдо рдХреНрдпрд╛ рдкрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ
рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдо рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдХрд┐рд╕реА рдмрд╛рд╣рд░реА рд╕рд░реНрд╡рд░ рдкрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдирд┐рд░рдВрддрд░ рдПрдХреАрдХрд░рдг рдкреНрд░рдгрд╛рд▓реА, рдФрд░ рдмрд┐рдЯрдмрдХреЗрдЯ рдПрдХ рдмрд╛рд╣рд░реА рд╕рд░реНрд╡рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рдХреЛ рдмрд╛рд╣рд░реА рд╕рд┐рд╕реНрдЯрдо рд╕реЗ рд╕рдВрдЧреНрд░рд╣реАрдд рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗред рдпрд╣реА рд╣реИ, рд╣рдореЗрдВ рдЕрдкрдиреЗ рдЦрд╛рддреЗ рдФрд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, Bitbucket рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЕрдзрд┐рдХреГрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдпрд╣ рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рд╡рд╣ рд╣рдорд╛рд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдмрдирд╛рдПрдВ рддрд╛рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣рдореЗрдВ Bitbucket рдореЗрдВ рдЕрдкрдиреА рд╕рд╛рдЦ рдХрд╛ рдЦреБрд▓рд╛рд╕рд╛ рди рдХрд░реЗред рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдп рд╣реИ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ - рдмрд┐рд▓реНрд▓реА рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИредOAuth2
OAuth2 рдПрдХ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ (рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдерд░реНрдб рдкрд╛рд░реНрдЯреА) рдХреЛ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рджрд┐рдП рдмрд┐рдирд╛ рд╕реАрдорд┐рдд рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рддреГрддреАрдп рдкрдХреНрд╖ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИредOAuth2 4 рднреВрдорд┐рдХрд╛рдУрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ:- рд╕рдВрд╕рд╛рдзрди рд╕реНрд╡рд╛рдореА
- рд╕рдВрд╕рд╛рдзрди рд╕рд░реНрд╡рд░
- рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░
- рдЧреНрд░рд╛рд╣рдХ (рдЖрд╡реЗрджрди)
рд╕рдВрд╕рд╛рдзрди рд╕реНрд╡рд╛рдореА рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реИ рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрд╕реЗ рд╕рдВрд╕рд╛рдзрди рд╕рд░реНрд╡рд░ рдкрд░ рд╣реЛрд╕реНрдЯ рдХрд┐рдП рдЧрдП рдЕрдкрдиреЗ рдЦрд╛рддреЗ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рджреЗрддрд╛ рд╣реИред рдЦрд╛рддреЗ рдореЗрдВ рдЖрд╡реЗрджрди рдХреА рдЕрдиреБрдорддрд┐ рджреА рдЧрдИ рдЕрдиреБрдорддрд┐рдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рд╕реАрдорд┐рдд рд╣реИред рд╕рдВрд╕рд╛рдзрди рд╕рд░реНрд╡рд░ рдореЗрдЬрдмрд╛рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЦрд╛рддреЛрдВ рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рддред рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд╕реНрд╡рд╛рдореА рдХреЛ рдкреНрд░рдорд╛рдгрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкрд╣реБрдВрдЪ рдЯреЛрдХрди рдЬрд╛рд░реА рдХрд░рддрд╛ рд╣реИред рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдПрдХ рд╕рд╛рде рдПрдХ рд╕рдВрд╕рд╛рдзрди рд╕рд░реНрд╡рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХ рдРрд╕рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЦрд╛рддреЗ рдФрд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд╣ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рд╡рд┐рдХрд╕рд┐рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ рдмрд┐рдЯрдмрдХреЗрдЯ рдПрдХ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдФрд░ рдПрдХ рд╕рдВрд╕рд╛рдзрди рд╕рд░реНрд╡рд░ рджреЛрдиреЛрдВ рд╣реЛрдЧрд╛редOAuth2 рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЗ рдЪрд╛рд░ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ: рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛрдб, рдирд┐рд╣рд┐рдд, рд╕рдВрд╕рд╛рдзрди рд╕реНрд╡рд╛рдореА рдкрд╛рд╕рд╡рд░реНрдб рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреНрд░реЗрдбреЗрдВрд╢рд┐рдпрд▓ред рд╣рдо рдЙрди рд╕рднреА рдкрд░ рд╡рд┐рдЪрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рд╣рдо рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛрдб рдХреЗ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛрдб рдкреНрд░рдХрд╛рд░ рд╕рд░реНрд╡рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд░реВрдк рд╕реЗ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реИ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реАрдХреНрд░реЗрдЯ рдХреЛрдб рдХреЛ рдЧреЛрдкрдиреАрдп рд░рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рдкреНрд░рдХрд╛рд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддреН, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЕрдкрдиреА рдкрд╣рдЪрд╛рди рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рдиреЗ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЕрдкрдиреЗ рдЦрд╛рддреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛редрдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛрдб рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рджреЛ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рдПрдХ рдХреНрд░рдо рд╣реЛрддрд╛ рд╣реИ:- рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдЕрдиреБрд░реЛрдз
- рдЯреЛрдХрди рдЕрдиреБрд░реЛрдз
рдПрдХ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдкрд╣рдЪрд╛рди рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдЕрдиреБрд░реЛрдз рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ GET рдЕрдиреБрд░реЛрдз рд╣реИ:- response_type - рдорд╛рди рдХреЛрдб рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП
- client_id - OAuth2 рдкреНрд░рджрд╛рддрд╛ рдХреЗ рд╕рд╛рде рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╕рдордп рдкреНрд░рд╛рдкреНрдд рдореВрд▓реНрдп
- рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ_рдпреВрд░реА - рдпреВрдЖрд░рдПрд▓ рдЬрд╣рд╛рдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЗ рдмрд╛рдж рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛
- рдЧреБрдВрдЬрд╛рдЗрд╢ - рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдкрд╣реБрдВрдЪ рд╕реНрддрд░ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ
- рд░рд╛рдЬреНрдп - рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмреЗрддрд░рддреАрдм рдврдВрдЧ рд╕реЗ рдЙрддреНрдкрдиреНрди рд╕реНрдЯреНрд░рд┐рдВрдЧ
рдЕрдиреБрд░реЛрдз рдЙрджрд╛рд╣рд░рдг:GET https://server.example.com/authorize?response_type=code&client_id=CLIENT_ID&state=xyz&redirect_uri=REDIRECT_URI
рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдкрдиреА рдкрд╣рдЪрд╛рди рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрдкрдиреЗ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рддрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рдкрд╣реБрдВрдЪ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рддреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдЬреЗрдВрдЯ рдХреЛ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рдкрдВрдЬреАрдХрд░рдг рдХреЗ рджреМрд░рд╛рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреЙрд▓рдмреИрдХ URL рдкрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛрдб рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛрдб рдФрд░ рд░рд╛рдЬреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдЕрдиреБрд░реЛрдз рдореЗрдВ рдкрд╛рд░рд┐рдд рдореВрд▓реНрдп рдХреЗ рд╕рд╛рде рд╣реЛрдЧрд╛редрдХреЙрд▓рдмреИрдХ рдЙрджрд╛рд╣рд░рдг:GET https://client.example.com/cb?code=AUTH_CODE_HERE&state=xyz
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдкреНрдд рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛрдб рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдХреНрд╕реЗрд╕ рдХреЛрдб рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдЕрдиреБрд░реЛрдз рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ POST рдЕрдиреБрд░реЛрдз рд╣реИ:- рдЕрдиреБрджрд╛рди_рдкреНрд░рдХрд╛рд░ - рдореВрд▓реНрдп рдкреНрд░рд╛рдзрд┐рдХрд░рдг_рдХреЛрдб рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП
- рдХреЛрдб - рдкрд┐рдЫрд▓реЗ рдЪрд░рдг рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЛрдб
- redirect_uri - рдкрд┐рдЫрд▓реЗ рдЪрд░рдг рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ URL рд╕реЗ рдореЗрд▓ рдЦрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП
- client_id - OAuth2 рдкреНрд░рджрд╛рддрд╛ рдХреЗ рд╕рд╛рде рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╕рдордп рдкреНрд░рд╛рдкреНрдд рдореВрд▓реНрдп
- client_secret - OAuth2 рдкреНрд░рджрд╛рддрд╛ рдХреЗ рд╕рд╛рде рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╕рдордп рдкреНрд░рд╛рдкреНрдд рдореВрд▓реНрдп
рдЕрдиреБрд░реЛрдз рдЙрджрд╛рд╣рд░рдг:POST https://server.example.com/token
grant_type=authorization_code&
code=AUTH_CODE&
redirect_uri=REDIRECT_URI&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдПрдХреНрд╕реЗрд╕ рдХреЛрдб рдФрд░ рдЙрд╕рдХрд╛ рдЬреАрд╡рдирдХрд╛рд▓ рд╣реЛрддрд╛ рд╣реИ:{
"access_token": "2YotnFZFEjr1zCsicMWpAA",
"expires_in": 3600,
"refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA"
}
рдпрд╣ рдкреВрд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╡рд╕рдВрдд рд╕реБрд░рдХреНрд╖рд╛ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╣реИ рдФрд░ рд╣рдореЗрдВ рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИредрдЧреНрд░рд╛рд╣рдХ рдкрдВрдЬреАрдХрд░рдг
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдПрдХ рдХреБрдВрдЬреА (рдХреБрдВрдЬреА) рдФрд░ рдПрдХ рдПрдХреНрд╕реЗрд╕ рдХреЛрдб (рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реАрдХреНрд░реЗрдЯ) рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд┐рдЯрдмрдХреЗрдЯ рдореЗрдВ рдПрдХ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВрдЧреЗред
рдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рдирд╛рдо рдФрд░ рдХреЙрд▓рдмреИрдХ URL рджрд░реНрдЬ рдХрд░реЗрдВред рдлрд┐рд░ рд╣рдо рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЗрд╕ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛ред
рдкреНрд░рд╛рдкреНрдд рдХреБрдВрдЬреА рдФрд░ ClientSecret рдорд╛рди рдХреЛ application.properties рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:client_id=ZJsdANfWkJ7jcktw2x
client_secret=28uUrJ9m43svbkcnXVNj8qeBjFtd8jaD
рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕реБрд░рдХреНрд╖рд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ
рдЗрд╕рдХреЗ рдмрд╛рдж, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕реБрд░рдХреНрд╖рд╛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВред OAuth2 рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ ClientRegistration рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛ред ClientRegademy OAuth2 рдкреНрд░рджрд╛рддрд╛ рдХреЗ рд╕рд╛рде рдкрдВрдЬреАрдХреГрдд рдЧреНрд░рд╛рд╣рдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИред рдпрд╣рд╛рдВ рд╣рдореЗрдВ рдкрд┐рдЫрд▓реЗ рдЪрд░рдг рдореЗрдВ рдкреНрд░рд╛рдкреНрдд client_id рдФрд░ client_secret рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЪреВрдБрдХрд┐ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдРрд╕реЗ рдХрдИ рдХреНрд▓рд╛рдЗрдВрдЯрдЧреНрд░реИрдЬреБрдПрдЯ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕рд┐рдХреНрдпреЛрд░рд┐рдЯреА рдХреНрд▓рд╛рдЗрдВрдЯрдЧреНрд░рд┐рдЧреЗрд░реЗрдЯрд░реАрдУрдкреЙрдЬрд╝рд┐рдЯрд░реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдФрд░ рдЙрди рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред рдЪрд▓реЛ рдЗрд╕реЗ рднреА рдмрдирд╛рддреЗ рд╣реИрдВред рд╣рдо рдпрд╣ рднреА рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдХреЗрд╡рд▓ рдПрдХ рдЕрдзрд┐рдХреГрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд┐рд╕реА рднреА рдЕрдиреБрд░реЛрдз рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗрд╡рд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИредSecurityConfig.java@Configuration
public class SecurityConfig {
@Value("${client_id}")
private String clientId;
@Value("${client_secret}")
private String clientSecret;
@Bean
public ClientRegistration clientRegistration() {
return ClientRegistration
.withRegistrationId("bitbucket")
.clientId(clientId)
.clientSecret(clientSecret)
.userNameAttributeName("username")
.clientAuthenticationMethod(BASIC)
.authorizationGrantType(AUTHORIZATION_CODE)
.userInfoUri("https://api.bitbucket.org/2.0/user")
.tokenUri("https://bitbucket.org/site/oauth2/access_token")
.authorizationUri("https://bitbucket.org/site/oauth2/authorize")
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
.build();
}
@Bean
@Autowired
public MyOAuth2UserService oAuth2userService(UserService userService) {
return new MyOAuth2UserService(userService);
}
@Bean
@Autowired
public ClientRegistrationRepository clientRegistrationRepository(List<ClientRegistration> registrations) {
return new InMemoryClientRegistrationRepository(registrations);
}
@Configuration
@EnableWebSecurity
public static class AuthConfig extends WebSecurityConfigurerAdapter {
private final MyOAuth2UserService userService;
@Autowired
public AuthConfig(MyOAuth2UserService userService) {
this.userService = userService;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests -> authorizeRequests
.anyRequest().authenticated()
)
.oauth2Login(oauth2Login -> oauth2Login
.userInfoEndpoint(userInfoEndpoint -> userInfoEndpoint.userService(userService))
);
}
}
}
рдЕрдиреБрдХреВрд▓рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗрд╡рд╛
рд╡рд╕рдВрдд рд╕реБрд░рдХреНрд╖рд╛ рди рдХреЗрд╡рд▓ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реИ, рдмрд▓реНрдХрд┐ рдЗрд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рднреА рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдЕрдиреБрд░реЛрдз рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ , рдПрдХ рдПрдХреНрд╕реЗрд╕ рдХреЛрдб рдХрд╛ рдЕрдиреБрд░реЛрдз , рд╕рд╛рде рд╣реА рдПрдХ рдПрдХреНрд╕реЗрд╕ рдХреЛрдб рдЕрдиреБрд░реЛрдз рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдХрд╕реНрдЯрдо рдкреЛрд╕реНрдЯ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ ред рд╕рдлрд▓ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЗ рдмрд╛рдж, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕рд┐рдХреНрдпреЛрд░рд┐рдЯреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдиреЗрдЯрд╡рд░реНрдХ рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдкреБрдирдГ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП UserInfo рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдЗрд╕рдХреЗ рд▓рд┐рдП OAuth2UserService рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИредрд╣рдо рдЗрд╕ рд╕реЗрд╡рд╛ рдХреЗ рдЕрдкрдиреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдмрдирд╛рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ, рддрд╛рдХрд┐ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдкрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрддрд┐рд░рд┐рдХреНрдд рд░реВрдк рд╕реЗ рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╡рд╣ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реИ, рдпрд╛ рдкрдВрдЬреАрдХрд░рдг рд╕рднреА рдХреЗ рд▓рд┐рдП рдЦреБрд▓рд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕реБрд░рдХреНрд╖рд╛ DefaultOAuth2UserService рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рд╡рд╣ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЖрдзрд╛рд░ рдмрдиреЗрдЧрд╛редMyOAuth2UserService.javapublic class MyOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
private static final String MISSING_USER_INFO_URI_ERROR_CODE = "missing_user_info_uri";
private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response";
private static final String MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE = "missing_user_name_attribute";
private static final ParameterizedTypeReference<Map<String, Object>> PARAMETERIZED_RESPONSE_TYPE = new ParameterizedTypeReference<Map<String, Object>>() {
};
private final UserService userService;
private final RestOperations restOperations;
private final Converter<OAuth2UserRequest, RequestEntity<?>> requestEntityConverter = new OAuth2UserRequestEntityConverter();
public MyOAuth2UserService(UserService userService) {
this.userService = requireNonNull(userService);
this.restOperations = createRestTemplate();
}
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
checkNotNull(userRequest, "userRequest cannot be null");
if (!StringUtils.hasText(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri())) {
OAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_INFO_URI_ERROR_CODE, "Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: " + userRequest.getClientRegistration().getRegistrationId(), null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
String registrationId = userRequest.getClientRegistration().getRegistrationId();
String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
if (!StringUtils.hasText(userNameAttributeName)) {
OAuth2Error oauth2Error = new OAuth2Error(
MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE,
"Missing required \"user name\" attribute name in UserInfoEndpoint for Client Registration: " + registrationId, null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
ResponseEntity<Map<String, Object>> response;
try {
response = this.restOperations.exchange(requestEntityConverter.convert(userRequest), PARAMETERIZED_RESPONSE_TYPE);
} catch (OAuth2AuthorizationException ex) {
OAuth2Error oauth2Error = ex.getError();
StringBuilder errorDetails = new StringBuilder();
errorDetails.append("Error details: [");
errorDetails.append("UserInfo Uri: ").append(
userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
errorDetails.append(", Error Code: ").append(oauth2Error.getErrorCode());
if (oauth2Error.getDescription() != null) {
errorDetails.append(", Error Description: ").append(oauth2Error.getDescription());
}
errorDetails.append("]");
oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE,
"An error occurred while attempting to retrieve the UserInfo Resource: " + errorDetails.toString(), null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex);
} catch (RestClientException ex) {
OAuth2Error oauth2Error = new OAuth2Error(INVALID_USER_INFO_RESPONSE_ERROR_CODE,
"An error occurred while attempting to retrieve the UserInfo Resource: " + ex.getMessage(), null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), ex);
}
Map<String, Object> userAttributes = emptyIfNull(response.getBody());
Set<GrantedAuthority> authorities = new LinkedHashSet<>();
authorities.add(new OAuth2UserAuthority(userAttributes));
for (String authority : userRequest.getAccessToken().getScopes()) {
authorities.add(new SimpleGrantedAuthority("SCOPE_" + authority));
}
User user = findOrCreate(userAttributes);
userAttributes.put(MyOAuth2User.ID_ATTR, user.getId());
return new MyOAuth2User(userNameAttributeName, userAttributes, authorities);
}
private User findOrCreate(Map<String, Object> userAttributes) {
String login = (String) userAttributes.get("username");
String username = (String) userAttributes.get("display_name");
Optional<User> userOpt = userService.findByLogin(login);
if (!userOpt.isPresent()) {
User user = new User();
user.setLogin(login);
user.setName(username);
return userService.create(user);
}
return userOpt.get();
}
private RestTemplate createRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
return restTemplate;
}
}
рдкрд░реАрдХреНрд╖рдг рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ
рд╣рдордиреЗ рдЬреЛ рдЕрднреА рдХрд┐рдпрд╛, рдЙрд╕рдХреЗ рд╕реНрд╡рд╛рд╕реНрдереНрдп рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдмрдирд╛рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдЕрдиреБрд░реЛрдз рд╢рд╛рдорд┐рд▓ рд╣реЛрдЧрд╛, рдЬреЛ рд╡рд░реНрддрдорд╛рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рдХрд░реЗрдЧрд╛редWelcomeEndpoint.java@Path("/")
public class WelcomeEndpoint {
@Autowired
private UserService userService;
@GET
public String welcome() {
User currentUser = getCurrentUser();
return String.format("Welcome, %s! (user id: %s, user login: %s)",
currentUser.getName(), currentUser.getId(), currentUser.getLogin());
}
public User getCurrentUser() {
return userService.findByLogin(getAuthenticatedUser().getName()).orElseThrow(() -> new RuntimeException("No user logged in."));
}
private Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
private MyOAuth2User getAuthenticatedUser() {
return (MyOAuth2User) getAuthentication().getPrincipal();
}
}
рд╕реНрд╡рд╛рд╕реНрдереНрдп рдЬрд╛рдВрдЪ
рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ http: // localhost: 8080 рдХреЗ рдкрддреЗ рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдЕрдкрдиреЗ рдЦрд╛рддреЗ рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд┐рдЯрдмрдХреЗрдЯ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдП рдЧрдП рдереЗред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рджрд░реНрдЬ рдХрд░реЗрдВред
рдЕрдм рд╣рдореЗрдВ рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдХреЛ рдЕрдкрдиреЗ рдЦрд╛рддреЗ рдФрд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рддрдХ рдкрд╣реБрдБрдЪ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЧреНрд░реАрдЯрд┐рдВрдЧ рдореЗрдВ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ рдФрд░ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА рджреЛрдиреЛрдВ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рд╣реИрдВред
рд╕реНрд░реЛрдд
рдЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдкреВрд░реНрдг рд╕реНрд░реЛрдд рдХреЛрдб Github рдкрд░ рд╣реИ редрд╕рдВрджрд░реНрдн