V
V
Vitali2012-10-08 01:04:04
API
Vitali, 2012-10-08 01:04:04

How to authorize a script to work with Vkontakte now?

There is a task to set up a video search through the Vkontakte API from the server.
Until recently, authorization was not solved very nicely, but it worked.

application_id = '123456'<br>
    application_secret = 'secretapplicationkey'<br>
    code_url = 'http://oauth.vk.com/oauth/authorize?client_id=***&scope=video&redirect_uri=http://vasja.ru&response_type=code&_hash=0'<br>
    email = '[email protected]'<br>
    password = 'password'<br><br>
    # Settings<br>
    tokenExpire = Settings.vkontakte[:expires]<br>
    token = Settings.vkontakte[:access_token]<br><br>
    if Time.current >= tokenExpire<br>
      puts '=== Logging in to vk.com and getting cookies ==='<br>
      resp = Net::HTTP.post_form(URI.parse('http://vk.com/login.php'),<br>
                                 {'m' => '1', 'email' => email, 'pass' => password})<br>
      cookies = resp.response['set-cookie']<br>
      remixsid = cookies.split('remixsid=')[1].split(';')[0].split(',')[0]<br><br>
      puts '=== Logging in once again with the cookies ==='<br>
      # Подключаемся снова к http://vk.com<br>
      header = { "Cookie" => 'remixsid=' + remixsid }<br>
      data = open(code_url, header)<br><br>
      resultURL = data.base_uri.to_s<br><br>
      puts '== Parsing URL for code param ==='<br>
      codeParams = Rack::Utils.parse_query URI(resultURL).query<br>
      code = codeParams['code']<br>
    end<br><br>
    puts '=== Authorizing ==='<br>
    if Time.current >= tokenExpire<br>
      app = VK::Serverside.new app_id: application_id, app_secret: application_secret<br>
      app.authorize code<br>
      Settings.vkontakte = { :access_token => app.access_token, :expires => (Time.current + app.expires_in) }<br>
    else<br>
      app = VK::Serverside.new app_id: application_id, app_secret: application_secret, access_token: token<br>
    end<br>

Then we already worked with the API as usual using a wrapper over the vk-ruby
API. But then, somewhere in the 20th of September, Vkontakte suddenly changed the order of authorization, which broke a huge number of scripts and services in different directions (For example, Loginza was also under attack ) . For example, they wrote about this on anti- chat .
Now just like that
resp = Net::HTTP.post_form(URI.parse('http://vk.com/login.php'),<br>
                                 {'m' => '1', 'email' => email, 'pass' => password})<br>

will no longer log in, he simply does not authorize and it is no longer possible to receive the Remixsid cookie.
We tried to go the legal way and use github.com/7even/vkontakte_api (Application server)
We get the token, everything is fine, but when we try to use video.search we get an error:
User authorization failed: method is unavailable with server auth.
Actually a question. How now, with little bloodshed, you can log in to vkontakte from the server and get a full-fledged access_token for further use with the API.
Thanks in advance for any help in resolving this issue :)

Answer the question

In order to leave comments, you need to log in

5 answer(s)
O
Oleg Bozhenko, 2012-10-08
@mrgall

I just changed
http://vk.com/?act=login&email=$email&pass=$pass
to
http://login.vk.com/?act=login&email=$email&pass=$pass
and my script worked.

M
mamantoha, 2012-10-23
@mamantoha

For example, like this:

# encoding: utf-8

require 'net/http'
require 'pp'

email = ARGV[0]
pass  = ARGV[1]

client_id     = '1915108'
scope         = 'friends'
redirect_uri  = 'http://oauth.vk.com/blank.html'
display       = 'wap'
response_type = 'token'

cookie = {}

puts "Открытие диалога авторизации"
# http://vk.com/developers.php?id=-1_37230422&s=1
url = "http://oauth.vk.com/oauth/authorize?client_id=#{client_id}&scope=#{scope}&redirect_uri=#{redirect_uri}&display=#{display}&response_type=#{response_type}&_hash=0"
puts url
uri = URI(url)

request = Net::HTTP::Get.new(uri.request_uri)

response = Net::HTTP.start(uri.host, uri.port){ |http| http.request(request) }

puts "Парсим ответ"
params = {
  _origin: response.body[/name="_origin" value="(.+?)"/, 1],
  ip_h:    response.body[/name="ip_h" value="(.+?)"/, 1],
  to:      response.body[/name="to" value="(.+?)"/, 1]
}

puts "Отправка формы"
url = /<form method="post" action="(.+?)"/.match(response.body)[1]
puts url
uri = URI(url)

params.merge!(email: email, pass: pass)

request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data(params)

response = Net::HTTP.start(uri.host, uri.port,
  :use_ssl => uri.scheme == 'https') {|http|
  http.request(request)
}

puts response['set-cookie']

cookie['l'] = /l=(.+?);/.match(response['set-cookie'])[1] rescue raise("Неверный логин или пароль")
cookie['p'] = /p=(.+?);/.match(response['set-cookie'])[1]

puts response.code
if response.code == '302'
  url = response['location']
end

puts "Разрешение доступа и получения куки"
uri = URI(url)
puts url

request = Net::HTTP::Get.new(uri.request_uri)

response = Net::HTTP.start(uri.host, uri.port,
  :use_ssl => uri.scheme == 'https') {|http|
  http.request(request)
}

cookie['remixsid'] = /remixsid=(.+?);/.match(response['set-cookie'])[1]
header = { "Cookie" => cookie.inject(''){ |memo, c| memo << "#{c[0]}=#{c[1]};" } }

# если пользователь этого еще не делал(response.code == '200'), надо дать приложению права
puts response.code
if response.code == '302'
  url = response['location']
end

puts "Установка куки"
uri = URI(url)
puts url

request = Net::HTTP::Get.new(uri.request_uri, header)

response = Net::HTTP.start(uri.host, uri.port,
  :use_ssl => uri.scheme == 'https') {|http|
  http.request(request)
}

puts "Получения access_token"
puts response.code
if response.code == '302'
  url = response['location']
  puts url
  access_token = /access_token=(.+?)&/.match(url)[1]
elsif response.code == '200'
  url = /<form method="POST" action="(.+?)"/.match(response.body)[1]
  puts url
  uri = URI(url)

  # Разрешаем доступ и отправляем форму
  request = Net::HTTP::Post.new(uri.request_uri, header)

  response = Net::HTTP.start(uri.host, uri.port,
    :use_ssl => uri.scheme == 'https') {|http|
    http.request(request)
  }

  puts response.code
  if response.code == '302'
    url = response['location']
    access_token = /access_token=(.+?)&/.match(url)[1]
  end
end

puts url
puts 'access_token=' + access_token

M
masterrr, 2012-10-08
@masterrr

Try vkontakte_api: ruby ​​adapter for VKontakte API
maybe?

7
7even, 2012-11-17
@7even

Get a suitable token once manually (by passing the offline parameter to the scope so that the token is infinite), put it in some yaml config on the server and read it from there to access the API.

Z
z0mb1ek, 2014-05-14
@z0mb1ek

mamantoha did the right thing, I can throw off the same code in java

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question