Skip to content

Instantly share code, notes, and snippets.

@lisp3r
Last active January 21, 2019 10:35
Show Gist options
  • Save lisp3r/68d9fc9e97c27a189ef8a0bdf3dd5f14 to your computer and use it in GitHub Desktop.
Save lisp3r/68d9fc9e97c27a189ef8a0bdf3dd5f14 to your computer and use it in GitHub Desktop.

Процедура аутентификации в Яндексе с получением токена для веб-приложения

Осуществляем описанную в документации процедуру без редиректа пользователя в браузер.

Нам понадобится:

  • client_id=ID - ID приложения
  • login=LOGIN - логин пользователя
  • passwd=PASS - пароль пользователя

1. Инициализируем куки

$ curl --cookie-jar jar --output /dev/null \
https://oauth.yandex.ru/authorize?response_type=token&client_id=ID

2. Отправляем логин и пароль пользоватея

$ curl -v --cookie jar --cookie-jar jar \
--data 'login=LOGIN' \
--data 'passwd=PASS' \
--data 'twoweeks=no' \
--data 'retpath=https://oauth.yandex.ru/authorize?response_type=token' \
https://passport.yandex.ru/auth?retpath=https%3A%2F%2Foauth.yandex.ru%2Fauthorize%3Fresponse_type%3Dtoken&mode=qr

В ответе приходит редирект с track_id:

< Location: 
https://passport.yandex.ru/auth/finish/?track_id=9f247041a0db64d1715a385a3187350702

Ничего с ним не делаем, только радуемся.

3. Отправляет client_id

Берем ссылку, указанную в первом пункте документации и отправляем туда client_id нашего приложения.

$ curl -v --cookie jar --cookie-jar jar \
--data 'client_id=ID' \
https://oauth.yandex.ru/authorize?response_type=token

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

4. Разрешаем доступ

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

$ curl -v --cookie jar --cookie-jar jar \
--data 'granted_scopes=directory:read_users' \
--data 'granted_scopes=directory:read_organization' \
--data 'granted_scopes=directory:read_groups' \
--data 'granted_scopes=directory:read_domains' \
--data 'granted_scopes=directory:read_departments' \
--data 'granted_scopes=tracker:read' \
--data 'csrf=7e5234b6ed81567112844732e62dcf3eee2e6551:1547983622222' \
--data 'response_type=token' \
--data 'redirect_uri=https://oauth.yandex.ru/verification_code' \
--data 'request_id=efeef51631834197af75ef2d4727ada6' \
--data 'retpath=https://oauth.yandex.ru/authorize?response_* Connection #0 to host oauth.yandex.ru left intact type=token' \
--data 'client_id=ID' \
https://oauth.yandex.ru/authorize/allow?response_type=token

В ответе приходит редирект с access_token:

< Location: 
https://oauth.yandex.ru/verification_code#access_token=AQAEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT00&token_type=bearer&expires_in=27842860

Токен сохраняем в приложении и используем для запросов к API Яндекса.

func main() {
	// 1. Инициализируем куки
	_url, err := url.Parse("https://oauth.yandex.ru/authorize?response_type=token&client_id=712bab09cb564e848cbb6418c4d875f2")

	jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
	client := &http.Client{
		Jar: jar,
	}

	if _, err = client.Get(_url.String()); err != nil {
		log.Fatal(err)
	}

	// 2. Отправляем логин и пароль пользоватея
	PostData := strings.NewReader("login="+email+"&passwd="+pass+"&twoweeks=no&retpath=https://oauth.yandex.ru/authorize?response_type=token")
	_url, err = url.Parse("https://passport.yandex.ru/auth?retpath=https%3A%2F%2Foauth.yandex.ru%2Fauthorize%3Fresponse_type%3Dtoken&mode=qr")
	if _, err = client.Post(_url.String(), "application/x-www-form-urlencoded" , PostData); err != nil {
		log.Fatal(err)
	}

	// 3 Отправляет client_id
	PostData = strings.NewReader("client_id="+client_id)
	_url, err = url.Parse("https://oauth.yandex.ru/authorize?response_type=token")
	resp, err := client.Post(_url.String(), "application/x-www-form-urlencoded" , PostData)

	if len(resp.Request.URL.Fragment) == 0 {
		// 4. Разрешаем доступ

		defer resp.Body.Close()
		var bodyString string
		if resp.StatusCode == http.StatusOK {
			bodyBytes, _ := ioutil.ReadAll(resp.Body)
			bodyString = string(bodyBytes)
		}

		csrf := ParseInputTag(bodyString, "csrf")
		request_id := ParseInputTag(bodyString, "request_id")
		_url, _ = url.Parse("https://oauth.yandex.ru/authorize/allow?response_type=token")
		checkboxData := "granted_scopes=directory:read_users&" +
			"granted_scopes=directory:read_organization&" +
			"granted_scopes=directory:read_groups&" +
			"granted_scopes=directory:read_domains&" +
			"granted_scopes=directory:read_departments&" +
			"granted_scopes=tracker:read&" +
			"csrf=" + csrf + "&" +
			"response_type=token&" +
			"redirect_uri=https://oauth.yandex.ru/verification_code&" +
			"request_id=" + request_id + "&" +
			"retpath=https://oauth.yandex.ru/authorize?response_* Connection #0 to host oauth.yandex.ru left intact type=token&" +
			"client_id="+client_id
		PostData = strings.NewReader(checkboxData)
		resp, _ = client.Post(_url.String(), "application/x-www-form-urlencoded" , PostData)

	}

	token := resp.Request.URL.Fragment
	s := strings.Split(token, "=")
	t := s[1]
	s = strings.Split(t, "&")
	token = s[0]

	fmt.Println(token) //AQAEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT00
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment