oauth

package
v2.16.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 3, 2023 License: MIT Imports: 9 Imported by: 0

README

Получение ключа доступа

PkgGoDev VK

Для работы со всеми методами API Вам необходимо передавать в запросе access_token — специальный ключ доступа. Он представляет собой строку из латинских букв и цифр и может соответствовать отдельному пользователю, сообществу или самому Вашему приложению.

ВКонтакте поддерживает несколько способов получения ключа доступа по OAuth 2.0:

  1. Implicit flow — требует встраивания браузера в ваше приложение. Ключ возвращается на устройство пользователя, где был открыт диалог авторизации (в виде дополнительного параметра URL). Такой ключ может быть использован только для запросов непосредственно с устройства пользователя.

  2. Authorization code flow — двухэтапный вариант с дополнительной аутентификацией Вашего сервера. Ключ доступа возвращается непосредственно на сервер и может быть использован, например, для автоматизированных запросов.

  3. Direct Authorization — прямая авторизация используя логин и пароль.

Права доступа приложения

VK

Права доступа определяют возможность использования токена для работы с тем или иным разделом данных. Так, например, для отправки личного сообщения от имени пользователя токен должен быть получен с правами oauth.ScopeUserMessage.

Обратите внимание, что некоторые права доступа пользователя из списка (например, messages) могут быть запрошены только Standalone-приложением — что означает необходимость использования Implicit Flow для запроса таких прав.

Если Вы хотите получить права на Доступ к друзьям и Доступ к статусам пользователя, то Ваша битовая маска будет равна:

scope := oauth.ScopeUserFriends + oauth.ScopeUserStatus // 1026

С помощью метода account.getAppPermissions, можно получить битовую маску настроек текущего пользователя в данном приложении.

Если, имея битовую маску 1026, Вы хотите проверить, имеет ли она доступ к друзьям — Вы можете сделать 1026 & 2.

scope, err := vk.AccountGetAppPermissions(nil)
if err != nil {
    log.Fatal(err)
}

if oauth.CheckScope(scope, oauth.ScopeUserFriends, oauth.ScopeUserStatus) {
    log.Println("Имеется доступ к друзьям и статусу")
}

Ключ доступа пользователя

Authorization code flow

VK

Используйте Authorization Code Flow для вызова методов API ВКонтакте с серверной части Вашего приложения. Ключ доступа, полученный таким способом, не привязан к IP-адресу, но набор прав, которые может получить приложение, ограничен из соображений безопасности.

Сгенерируйте адрес
acf := NewAuthCodeFlowUser(oauth.UserParams{
    ClientID:    123456,
    RedirectURI: "https://example.com/callback",
    Scope:       oauth.ScopeUserPhotos + oauth.ScopeUserDocs,
}, clientSecret)
u := acf.URL().String()

Необходимо перенаправить браузер пользователя по сгенерированному адресу.

Если пользователь не вошел на сайт, то в диалоговом окне ему будет предложено ввести свой логин и пароль.

Разрешение прав доступа

После успешного входа на сайт пользователю будет предложено авторизовать приложение, разрешив доступ к необходимым настройкам, запрошенным при помощи параметра scope.

Получение access_token

После успешной авторизации приложения браузер пользователя будет перенаправлен по адресу redirect_uri, указанному при открытии диалога авторизации. При этом код для получения ключа доступа code будет передан как GET-параметр.

func callback(w http.ResponseWriter, req *http.Request) {
    t, err := acf.Token(req.URL)
    if err != nil {
        fmt.Printf("%#v\n", err)
    }

    fmt.Printf(
        "Токен %s для id%d действует %d секунд",
        t.AccessToken,
        t.UserID,
        t.ExpiresIn,
    )
}

acf.Token(req.URL) выполнит запрос с вашего сервера, чтобы получить ключ доступа.

Implicit flow

VK

Используйте Implicit Flow для вызова методов API ВКонтакте непосредственно с устройства пользователя.

Сгенерируйте адрес
u := oauth.ImplicitFlowUser(oauth.UserParams{
    ClientID: 123456,
    Scope:    oauth.ScopeUserPhotos + oauth.ScopeUserDocs,
})

RedirectURI по умолчанию https://oauth.vk.com/blank.html

Разрешение прав доступа

Необходимо перенаправить встроенный браузер по адресу сгенерированному на предыдущем шаге.

Рекомендуется проверять, что страница вернула код 200. Если код отличается, а content-type содержит JSON, необходимо распарсить этот JSON в ошибку:

var errOAuth oauth.Error
err = json.Unmarshal(data, &errOAuth)

Если пользователь не авторизован ВКонтакте в используемом браузере, то в диалоговом окне ему будет предложено ввести свой логин и пароль.

После успешного входа на сайт пользователю будет предложено авторизовать приложение, разрешив доступ к необходимым настройкам, запрошенным при помощи параметра scope.

Получение access_token

После успешной авторизации приложения браузер пользователя будет перенаправлен по адресу redirect_uri, указанному при открытии диалога авторизации. При этом ключ доступа к API access_token и другие параметры будут переданы в URL-фрагменте ссылки.

t, err := oauth.NewUserTokenFromURL(u)
if err != nil {
    fmt.Printf("%#v\n", err)
}

fmt.Printf(
    "Токен %s для id%d действует %d секунд",
    t.AccessToken,
    t.UserID,
    t.ExpiresIn,
)

ExpiresIn содержит 0, если токен бессрочный (при использовании scope=offline).

Direct Authorization

VK

Внимание! Доступ к этому типу авторизации может быть получен только после предварительного согласования с администрацией ВКонтакте.

Для подачи заявки на получение доступа Вам необходимо обратиться в службу поддержки, указав ID Вашего приложения.

В настоящий момент эта возможность предоставляется только для платформ, не поддерживающих стандартную авторизацию. В заявке необходимо кратко описать функционал приложения.

Доверенные приложения могут получить неограниченный по времени access_token для доступа к API, передав логин и пароль пользователя.

Обратите внимание, что приложение не должно хранить пароль пользователя. Выдаваемый access_token не привязан к IP-адресу пользователя, поэтому его достаточно для последующей работы с API без повторения процедуры авторизации.

func example(params oauth.DirectAuthParams) (*oauth.UserToken, error) {
	t, err := oauth.DirectAuth(params)
	if err == nil {
		return t, nil
	}

	var e *oauth.Error
	if !errors.As(err, &e) {
		return nil, err
	}

	switch e.Type {
	case oauth.ErrNeedCaptcha:
		message := "Требуется ввести код с картинки:\n"
		message += e.CaptchaImg

		_, _ = fmt.Println(message)

		// ...

		params.CaptchaKey = ""
		params.CaptchaSID = e.CaptchaSID

		return example(params)
	case oauth.ErrNeedValidation:
		message := "Введите код"

		switch e.ValidationType {
		case oauth.ValidationSMS:
			message += ", который пришел в сообщении на номер " + e.PhoneMask
		case oauth.ValidationApp:
			message += " из приложения для генерации кодов"
		}

		fmt.Println(message)

		// ...

		params.Code = ""

		return example(params)
	}

	return nil, err
}


params := DirectAuthParams{
    ClientSecret: "secret",
    ClientID:     123456,
    Scope:        oauth.ScopeUserPhotos + oauth.ScopeUserDocs,
}

params.Username = "username"
params.Password = "password"

t, err := example(params)
if err != nil {
    fmt.Printf("%#v\n", err)
}


fmt.Printf(
    "Токен %s для id%d действует %d секунд",
    t.AccessToken,
    t.UserID,
    t.ExpiresIn,
)

Ключ доступа сообщества

Получение списка администрируемых сообществ

Получить ключ доступа сообщества через OAuth может только его администратор. Чтобы получить ключи доступа сразу для всех или нескольких сообществ пользователя, мы рекомендуем добавить этот дополнительный шаг в процесс авторизации.

Получите ключ доступа пользователя с правами scope=groups и сделайте запрос к методу groups.get с параметром filter=admin, чтобы получить список идентификаторов администрируемых сообществ.

Затем используйте все полученные значения или их часть в качестве параметра GroupIDs.

Authorization code flow

VK

Используйте Authorization Code Flow для вызова методов API ВКонтакте с серверной части Вашего приложения. Ключ доступа, полученный таким способом, не привязан к IP-адресу.

Сгенерируйте адрес
acf := NewAuthCodeFlowGroup(oauth.GroupParams{
    ClientID:    123456,
    GroupIDs:    []int{1234},
    RedirectURI: "https://example.com/callback",
    Scope:       oauth.ScopeGroupPhotos + oauth.ScopeGroupDocs,
}, clientSecret)
u := acf.URL().String()

Необходимо перенаправить браузер пользователя по сгенерированному адресу.

Если пользователь не вошел на сайт, то в диалоговом окне ему будет предложено ввести свой логин и пароль.

Получение access_token

После успешной авторизации приложения браузер пользователя будет перенаправлен по адресу redirect_uri, указанному при открытии диалога авторизации. При этом код для получения ключа доступа code будет передан как GET-параметр.

func callback(w http.ResponseWriter, req *http.Request) {
    t, err := acf.Token(req.URL)
    if err != nil {
        fmt.Printf("%#v\n", err)
    }

    for _, groupToken := range t.Groups {
        fmt.Printf(
            "Токен %s для club%d действует %d секунд",
            groupToken.AccessToken,
            groupToken.GroupID,
            t.ExpiresIn,
        )
    }
}

acf.Token(req.URL) выполнит запрос с вашего сервера, чтобы получить ключ доступа.

Implicit flow

VK

Используйте Implicit Flow для вызова методов API ВКонтакте непосредственно с устройства пользователя.

Сгенерируйте адрес

Перед открытием диалога авторизации рекомендуется убедиться, что пользователь является администратором сообщества, для которого необходимо получить ключ доступа

u := oauth.ImplicitFlowGroup(oauth.GroupParams{
    ClientID: 123456,
    GroupIDs: []int{1234},
    Scope:    oauth.ScopeGroupPhotos + oauth.ScopeGroupDocs,
})

RedirectURI по умолчанию https://oauth.vk.com/blank.html

Разрешение прав доступа

Необходимо перенаправить встроенный браузер по адресу сгенерированному на предыдущем шаге.

Рекомендуется проверять, что страница вернула код 200. Если код отличается, а content-type содержит JSON, необходимо распарсить этот JSON в ошибку:

var errOAuth oauth.Error
err = json.Unmarshal(data, &errOAuth)

После успешного входа на сайт пользователю будет предложено авторизовать приложение, разрешив доступ к необходимым настройкам, запрошенным при помощи параметра scope.

Получение access_token

После успешной авторизации приложения браузер пользователя будет перенаправлен по адресу redirect_uri, указанному при открытии диалога авторизации. При этом ключ доступа к API access_token и другие параметры будут переданы в URL-фрагменте ссылки.

t, err := oauth.NewGroupTokensFromURL(u)
if err != nil {
    fmt.Printf("%#v\n", err)
}

for _, groupToken := range t.Groups {
    fmt.Printf(
        "Токен %s для club%d действует %d секунд",
        groupToken.AccessToken,
        groupToken.GroupID,
        t.ExpiresIn,
    )
}

Сервисный ключ доступа

Сервисный ключ нужен для запросов, которые не требуют авторизации пользователя или сообщества. Это такие методы, как secure.sendNotification для отправки уведомлений от приложения, или secure.addAppEvent для добавления информации о достижениях, а также, начиная с апреля 2017 года, открытые методы, например, users.get.

Получить сервисный ключ доступа можно в настройках Вашего приложения. Ключ не привязан к IP-адресу при использовании с открытыми методами, срок его действия не ограничен. Если ключ был скомпрометирован, Вы можете сгенерировать новый ключ, при этом старый будет аннулирован.

Сервисный ключ доступа идентифицирует Ваше приложение. Все запросы к API, совершённые с использованием Вашего ключа доступа, будут считаться совершёнными от имени Вашего приложения. Сервисный ключ доступа можно использовать только для запросов с серверной стороны приложения, его нельзя передавать и хранить на клиенте.

Documentation

Overview

Package oauth ...

Package oauth ...

Package oauth ...

Package oauth ...

Index

Constants

View Source
const (
	ScopeUserNotify        = 1 << 0
	ScopeUserFriends       = 1 << 1
	ScopeUserPhotos        = 1 << 2
	ScopeUserAudio         = 1 << 3
	ScopeUserVideo         = 1 << 4
	ScopeUserStories       = 1 << 6
	ScopeUserPages         = 1 << 7
	ScopeUserMenu          = 1 << 8
	ScopeUserWallmenu      = 1 << 9
	ScopeUserStatus        = 1 << 10
	ScopeUserNotes         = 1 << 11
	ScopeUserMessages      = 1 << 12
	ScopeUserWall          = 1 << 13
	ScopeUserAds           = 1 << 15
	ScopeUserOffline       = 1 << 16
	ScopeUserDocs          = 1 << 17
	ScopeUserGroups        = 1 << 18
	ScopeUserNotifications = 1 << 19
	ScopeUserStats         = 1 << 20
	ScopeUserEmail         = 1 << 22
	ScopeUserAdsweb        = 1 << 23
	ScopeUserLeads         = 1 << 24
	ScopeUserGroupMessages = 1 << 25
	ScopeUserExchange      = 1 << 26
	ScopeUserMarket        = 1 << 27
	ScopeUserPhone         = 1 << 28
)

Access Permissions for User Token.

View Source
const (
	ScopeGroupStories   = 1 << 0
	ScopeGroupPhotos    = 1 << 2
	ScopeGroupAppWidget = 1 << 6
	ScopeGroupMessages  = 1 << 12
	ScopeGroupDocs      = 1 << 17
	ScopeGroupManage    = 1 << 18
)

Access Permissions for Community Token.

Variables

View Source
var (
	OAuthHost          = "oauth.vk.com"
	DefaultRedirectURI = "https://oauth.vk.com/blank.html"
)

Functions

func CheckScope

func CheckScope(scope int, permissions ...int) bool

CheckScope ...

func ImplicitFlowGroup

func ImplicitFlowGroup(p GroupParams) *url.URL

ImplicitFlowGroup need to run methods directly from users devices. Access token received this way can not be used for server requests.

https://vk.com/dev/implicit_flow_group

func ImplicitFlowUser

func ImplicitFlowUser(p UserParams) *url.URL

ImplicitFlowUser need to run methods directly from users devices. Access token received this way can not be used for server requests.

https://vk.com/dev/implicit_flow_user

Types

type AuthCodeFlowGroup

type AuthCodeFlowGroup struct {
	Client    *http.Client
	UserAgent string
	// contains filtered or unexported fields
}

AuthCodeFlowGroup need to run VK API methods from the server side of an application. Access token received this way is not bound to an ip address.

https://vk.com/dev/authcode_flow_group

func NewAuthCodeFlowGroup

func NewAuthCodeFlowGroup(p GroupParams, clientSecret string) *AuthCodeFlowGroup

NewAuthCodeFlowGroup returns a new AuthcodeFlowGroup.

func (AuthCodeFlowGroup) Token

func (a AuthCodeFlowGroup) Token(u *url.URL) (*GroupTokens, error)

Token ...

func (AuthCodeFlowGroup) URL

func (a AuthCodeFlowGroup) URL() *url.URL

URL authorization dialog.

type AuthCodeFlowUser

type AuthCodeFlowUser struct {
	Client    *http.Client
	UserAgent string
	// contains filtered or unexported fields
}

AuthCodeFlowUser need to run VK API methods from the server side of an application. Access token received this way is not bound to an ip address but set of permissions that can be granted is limited for security reasons.

https://vk.com/dev/authcode_flow_user

func NewAuthCodeFlowUser

func NewAuthCodeFlowUser(p UserParams, clientSecret string) *AuthCodeFlowUser

NewAuthCodeFlowUser returns a new AuthcodeFlowUser.

func (AuthCodeFlowUser) Token

func (a AuthCodeFlowUser) Token(u *url.URL) (*UserToken, error)

Token ...

func (AuthCodeFlowUser) URL

func (a AuthCodeFlowUser) URL() *url.URL

URL authorization dialog.

type DirectAuthParams

type DirectAuthParams struct {
	ClientSecret       string
	ClientID           int
	Username, Password string

	Scope int
	V     string

	TwoFactorSupported bool
	ForceSMS           bool
	Code               string

	CaptchaSID string
	CaptchaKey string

	TestRedirectURI bool

	Client    *http.Client
	UserAgent string
}

DirectAuthParams parameters.

type Display

type Display string

Display sets authorization page appearance.

const (
	Page   Display = "page"   // authorization form in a separate window
	Popup  Display = "popup"  // a pop-up window
	Mobile Display = "mobile" // authorization for mobile devices (uses no Javascript).
)

The supported values.

type Error

type Error struct {
	Type        ErrorType   `json:"error"`
	Reason      ErrorReason `json:"error_reason,omitempty"`
	Description string      `json:"error_description,omitempty"`

	// For auth direct
	CaptchaSID     string         `json:"captcha_sid,omitempty"`
	CaptchaImg     string         `json:"captcha_img,omitempty"`
	RedirectURI    string         `json:"redirect_uri,omitempty"`
	ValidationType ValidationType `json:"validation_type,omitempty"`
	PhoneMask      string         `json:"phone_mask,omitempty"`
}

Error for oauth.

func (Error) Error

func (e Error) Error() string

Error returns the message of a Error.

func (Error) Is

func (e Error) Is(target error) bool

Is unwraps its first argument sequentially looking for an error that matches the second.

type ErrorReason

type ErrorReason string

ErrorReason for oauth.

const (
	ErrUserDenied ErrorReason = "user_denied"
)

ErrorReason types.

func (ErrorReason) Error

func (e ErrorReason) Error() string

Error returns the message of a Error.

type ErrorType

type ErrorType string

ErrorType for oauth.

const (
	ErrInvalidRequest          ErrorType = "invalid_request"
	ErrUnauthorizedClient      ErrorType = "unauthorized_client"
	ErrUnsupportedResponseType ErrorType = "unsupported_response_type"
	ErrInvalidScope            ErrorType = "invalid_scope"
	ErrServerError             ErrorType = "server_error"
	ErrTemporarilyUnavailable  ErrorType = "temporarily_unavailable"
	ErrAccessDenied            ErrorType = "access_denied"

	ErrInvalidGrant ErrorType = "invalid_grant"

	ErrNeedValidation ErrorType = "need_validation"
	ErrNeedCaptcha    ErrorType = "need_captcha"
)

Error types.

See https://tools.ietf.org/html/rfc6749#section-4.2.2.1

func (ErrorType) Error

func (e ErrorType) Error() string

Error returns the message of a Error.

type GroupParams

type GroupParams struct {
	ClientID    int // required
	RedirectURI string
	GroupIDs    []int
	Display     Display // Default mobile
	Scope       int
	V           string // Default version module
	State       string
}

GroupParams struct.

func (GroupParams) Values

func (p GroupParams) Values() *url.Values

Values ...

type GroupToken

type GroupToken struct {
	GroupID     int    `json:"group_id"`
	AccessToken string `json:"access_token"`
}

GroupToken struct with access token.

type GroupTokens

type GroupTokens struct {
	Groups    []GroupToken `json:"groups"`
	ExpiresIn int          `json:"expires_in"`
}

GroupTokens struct with access tokens.

func NewGroupTokensFromJSON

func NewGroupTokensFromJSON(data []byte) (*GroupTokens, error)

NewGroupTokensFromJSON return group tokens.

func NewGroupTokensFromURL

func NewGroupTokensFromURL(u *url.URL) (*GroupTokens, error)

NewGroupTokensFromURL return group tokens.

type UserParams

type UserParams struct {
	ClientID    int // required
	RedirectURI string
	Display     Display // Default mobile
	Scope       int
	V           string // Default version module
	State       string
}

UserParams struct.

func (UserParams) Values

func (p UserParams) Values() *url.Values

Values ...

type UserToken

type UserToken struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
	UserID      int    `json:"user_id"`
	Email       string `json:"email,omitempty"`
	State       string `json:"state,omitempty"`
}

UserToken ...

func DirectAuth

func DirectAuth(p DirectAuthParams) (*UserToken, error)

DirectAuth type of authorization.

Please note! This type of authorization is available only after preliminary approval of VK administration.

To apply for access you need to contact our support service at https://vk.com/support and specify you application ID.

Currently, this functionality is available only for the following categories:

- Fully functional clients. At the time you apply for access your application shall be functional (using standard authorization); and you shall provide the download link in the request.

- Applications for platforms which do not support standard authorization. Provide a short description of application functionality in the request.

Trusted applications can get time-unlimited access_token to access API by passing user's login and password.

Note that application shall not store user's password. Issued access_token is not bound to user's IP address, that is why it is sufficient for using API in the future without repeating authorization procedure.

See https://vk.com/dev/auth_direct

func NewUserTokenFromJSON

func NewUserTokenFromJSON(data []byte) (*UserToken, error)

NewUserTokenFromJSON ...

func NewUserTokenFromURL

func NewUserTokenFromURL(u *url.URL) (*UserToken, error)

NewUserTokenFromURL ...

type ValidationType

type ValidationType string

ValidationType ...

const (
	ValidationSMS ValidationType = "2fa_sms"
	ValidationApp ValidationType = "2fa_app"
)

Possible values.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL