Skip to content

Commit 92f3f1d

Browse files
authored
Merge pull request #2 from danschultzer/vkontakte
Add vkontakte support
2 parents 601f08d + 98a6b2b commit 92f3f1d

File tree

3 files changed

+146
-2
lines changed

3 files changed

+146
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
[![Build Status](https://travis-ci.org/danschultzer/coherence_assent.svg?branch=master)](https://travis-ci.org/danschultzer/coherence_assent)
44

5-
Use Google, Github, Twitter, Facebook, Basecamp, or add your own strategy for authorization to your Coherence Phoenix app.
5+
Use Google, Github, Twitter, Facebook, Basecamp, VK or add your own strategy for authorization to your Coherence Phoenix app.
66

77
## Features
88

99
* Collects required login field if missing verified email from provider
1010
* Multiple providers can be used for accounts
1111
* When removing auth: Validates user has password or another provider authentication
12-
* Github, Google, Twitter, Facebook and Basecamp strategies included
12+
* Github, Google, Twitter, Facebook, Basecamp and VK strategies included
1313
* Updates Coherence templates automatically
1414
* You can add your custom strategy with ease
1515

lib/coherence_assent/strategies/vk.ex

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
defmodule CoherenceAssent.Strategy.VK do
2+
@moduledoc """
3+
VK.com OAuth 2.0 strategy.
4+
"""
5+
6+
alias CoherenceAssent.Strategy.Helpers
7+
alias CoherenceAssent.Strategies.OAuth2, as: OAuth2Helper
8+
9+
def authorize_url(conn, config) do
10+
OAuth2Helper.authorize_url(conn, set_config(config))
11+
end
12+
13+
def callback(conn, config, params) do
14+
config = set_config(config)
15+
client = OAuth2.Client.new(config)
16+
17+
conn
18+
|> OAuth2Helper.check_conn(client, params)
19+
|> OAuth2Helper.get_access_token(config, params)
20+
|> get_user(config)
21+
|> get_response()
22+
|> normalize()
23+
end
24+
25+
defp set_config(config) do
26+
profile_fields = ["uid", "first_name", "last_name",
27+
"photo_200", "screen_name", "verified"]
28+
29+
user_url_params = %{
30+
"fields" => Enum.join(profile_fields, ","),
31+
"v" => "5.69",
32+
"https" => "1"
33+
} |> Map.merge(config[:user_url_params] || %{})
34+
35+
[
36+
site: "https://api.vk.com",
37+
authorize_url: "https://oauth.vk.com/authorize",
38+
token_url: "https://oauth.vk.com/access_token",
39+
user_url: "/method/users.get",
40+
authorization_params: [scope: "email"],
41+
user_url_params: user_url_params
42+
]
43+
|> Keyword.merge(config)
44+
|> Keyword.put(:strategy, OAuth2.Strategy.AuthCode)
45+
end
46+
47+
defp get_user({:ok, %{conn: conn, client: client}}, config) do
48+
user_url_params = config[:user_url_params] |> Map.put("access_token", client.token.access_token)
49+
user_url = config[:user_url] <> "?" <> URI.encode_query(user_url_params)
50+
51+
OAuth2Helper.get_user({:ok, %{conn: conn, client: client}}, user_url)
52+
end
53+
defp get_user({:error, _} = error, _config), do: error
54+
55+
defp get_response({:ok, %{client: client, user: %{"response" => [user]}} = resp}) do
56+
email = Map.get(client.token.other_params, "email")
57+
user = Map.put_new(user, "email", email)
58+
59+
{:ok, Map.put(resp, :user, user)}
60+
end
61+
defp get_response({:ok, resp}), do: {:error, %{error: "Retrieved invalid response: #{inspect resp.user}"}}
62+
defp get_response(resp), do: resp
63+
64+
defp normalize({:ok, %{conn: conn, client: client, user: user}}) do
65+
user = %{"uid" => user["id"] |> to_string,
66+
"nickname" => user["screen_name"],
67+
"first_name" => user["first_name"],
68+
"last_name" => user["last_name"],
69+
"name" => [user["first_name"], user["last_name"]] |> Enum.join(" "),
70+
"email" => user["email"],
71+
"image" => user["photo_200"],
72+
"verified" => user["verified"] > 0}
73+
|> Helpers.prune
74+
75+
{:ok, %{conn: conn, client: client, user: user}}
76+
end
77+
defp normalize({:error, _} = error), do: error
78+
end
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
defmodule CoherenceAssent.VKTest do
2+
use CoherenceAssent.Test.ConnCase
3+
4+
import OAuth2.TestHelpers
5+
alias CoherenceAssent.Strategy.VK
6+
7+
setup %{conn: conn} do
8+
conn = session_conn(conn)
9+
10+
bypass = Bypass.open
11+
config = [site: bypass_server(bypass),
12+
authorize_url: "/authorize",
13+
token_url: "/access_token"]
14+
params = %{"code" => "test", "redirect_uri" => "test"}
15+
16+
{:ok, conn: conn, config: config, params: params, bypass: bypass}
17+
end
18+
19+
test "authorize_url/2", %{conn: conn, config: config} do
20+
assert {:ok, %{conn: _conn, url: url}} = VK.authorize_url(conn, config)
21+
assert url =~ "/authorize"
22+
end
23+
24+
describe "callback/2" do
25+
test "normalizes data", %{conn: conn, config: config, params: params, bypass: bypass} do
26+
users = [%{"id" => 210700286,
27+
"first_name" => "Lindsay",
28+
"last_name" => "Stirling",
29+
"screen_name" => "lindseystirling",
30+
"verified" => 1}]
31+
32+
Bypass.expect_once bypass, "POST", "/access_token", fn conn ->
33+
send_resp(conn, 200, Poison.encode!(%{"access_token" => "access_token", "email" => "lindsay.stirling@example.com"}))
34+
end
35+
36+
Bypass.expect_once bypass, "GET", "/method/users.get", fn conn ->
37+
query = Plug.Conn.fetch_query_params(conn)
38+
39+
assert query.params["fields"] == "uid,first_name,last_name,photo_200,screen_name,verified"
40+
assert query.params["v"] == "5.69"
41+
assert query.params["access_token"] == "access_token"
42+
43+
users = [%{"id" => 210700286,
44+
"first_name" => "Lindsay",
45+
"last_name" => "Stirling",
46+
"screen_name" => "lindseystirling",
47+
"photo_200" => "https://pp.userapi.com/c840637/v840637830/2d20e/wMuAZn-RFak.jpg",
48+
"verified" => 1}]
49+
50+
Plug.Conn.resp(conn, 200, Poison.encode!(%{"response" => users}))
51+
end
52+
53+
expected = %{"email" => "lindsay.stirling@example.com",
54+
"first_name" => "Lindsay",
55+
"last_name" => "Stirling",
56+
"name" => "Lindsay Stirling",
57+
"nickname" => "lindseystirling",
58+
"uid" => "210700286",
59+
"image" => "https://pp.userapi.com/c840637/v840637830/2d20e/wMuAZn-RFak.jpg",
60+
"verified" => true}
61+
62+
{:ok, %{user: user}} = VK.callback(conn, config, params)
63+
assert expected == user
64+
end
65+
end
66+
end

0 commit comments

Comments
 (0)