рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕реБрд░рдХреНрд╖рд╛ - рдПрдХ OAuth2 рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╡реЗрдм рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдЙрджрд╛рд╣рд░рдг рдмрд┐рдЯрдмрдХреЗрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ

рдЗрд╕ рдЖрд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдмрд╛рд╣рд░реА рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рд░реНрд╡рд░ (рдмрд┐рдЯрдмрдХреЗрдЯ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ) 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.java
public 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 {
            // OAuth2UserRequestEntityConverter cannot return null values.
            //noinspection ConstantConditions
            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 рдкрд░ рд╣реИ ред

рд╕рдВрджрд░реНрдн



All Articles