Revision 844
- Date:
- 2022/11/25 09:45:08
- Files:
Legend:
- Added
- Removed
- Modified
-
utf8/plugins/session/comps/www/oauth/yandex.html
1 <!DOCTYPE html> 2 <head> 3 <script type="text/javascript"> 4 <!-- 5 opener.location.reload(true); 6 close(); 7 //--> 8 </script> 9 </head> 10 </html> 11 <%doc> 12 13 use LWP::UserAgent; 14 use JSON::XS; 15 use URI; 16 use Encode; 17 use URI; 18 use URI::QueryParam; 19 my $JSON = JSON::XS->new->utf8; 20 21 Manual redirect: 22 use session::AUTH::VKontakte; 23 my $site = $state->development ? 'www' : 'www'; 24 my $vk_connect = session::AUTH::VKontakte->new( 25 vk_redirect_uri => 'http://'.$site.'/oauth/vkontakte.html', 26 ); 27 28 29 </%doc> 30 <%once> 31 32 my $site = $state->development ? '' : ''; 33 34 </%once> 35 <%args> 36 37 $code => undef 38 39 </%args> 40 <%init> 41 42 my $res; 43 my $info; 44 45 my $vk_connect = session::AUTH::VKontakte->new; 46 my $auth_url = $vk_connect->authorize_url; 47 if ( $code ) { 48 my $local_session = $vk_connect->authenticate( code => $code ); 49 if ( ref $local_session eq 'session::Session' && $local_session->id ) { 50 my $profile = $keeper->{users}->get_profile( id => $local_session->id ) if exists $keeper->{users}; 51 if ( ref $profile ) { 52 unless ( exists $local_session->{avatar} ) { 53 my $avatar = $profile->get_image('avatar'); 54 $session->{avatar} = ref $avatar && exists $avatar->{filename} ? $avatar->{mini}{'54x54'}{filename} : undef; 55 $local_session->set ( 56 name => $profile->name_full, 57 last_name => $profile->name_family, 58 first_name => $profile->name_part, 59 avatar => $session->{avatar}, 60 ); 61 } else { 62 $local_session->set ( 63 name => $profile->name_full, 64 last_name => $profile->name_family, 65 first_name => $profile->name_part, 66 ); 67 } 68 } 69 } 70 } elsif ( $auth_url ) { 71 $m->redirect($auth_url->as_string); 72 } else { 73 &abort404 unless $DEBUG; 74 } 75 76 </%init> -
utf8/plugins/session/lib/session/AUTH/Yandex.pm
1 package session::AUTH::Yandex; 2 3 use strict; 4 use warnings; 5 use LWP::UserAgent; 6 use IO::Socket::SSL; 7 use JSON::XS; 8 use Data::Dumper; 9 use URI; 10 use URI::QueryParam; 11 use HTTP::Request; 12 use Encode; 13 use Contenido::Globals; 14 15 use vars qw($VERSION); 16 $VERSION = '4.1'; 17 18 =for rem 19 yandex: 20 auto_create_user: 1 21 app_id: decimal digits 22 app_secret: 32 hex digits 23 authorize_url: https://oauth.yandex.ru/authorize 24 access_token_url: https://oauth.yandex.ru/token 25 user_info_url: GET https://login.yandex.ru/info? 26 [ format=json | xml | jwt] 27 [& jwt_secret=<Cекретный ключ>] 28 [& with_openid_identity=1 | yes | true] 29 Authorization: OAuth <OAuth-токен> 30 =cut 31 32 our $JSON = JSON::XS->new->utf8; 33 34 =for rem SCHEMA 35 36 $m->redirect ( $yandex_connect->authorize_url( yandex_redirect_uri => ... )->as_string ); 37 38 39 =cut 40 41 our %SCOPE = ( 42 'notify' => 1, 43 'friends' => 2, 44 'photos' => 4, 45 'audio' => 8, 46 'video' => 16, 47 'docs' => 131072, 48 'notes' => 2048, 49 'pages' => 128, 50 'menu_link' => 256, 51 'status' => 1024, 52 'groups' => 262144, 53 'email' => 4194304, 54 'notifications' => 524288, 55 'stats' => 1048576, 56 'ads' => 32768, 57 'offline' => 65536, 58 ); 59 60 sub new { 61 my ($class, %config) = @_; 62 my $self = bless {}, $class; 63 64 $self->{yandex_authorize_url} = 'https://oauth.yandex.ru/authorize'; 65 $self->{yandex_access_token_url} = 'https://oauth.yandex.ru/token'; 66 $self->{yandex_user_info_url} = 'https://login.yandex.ru/info'; 67 68 for (qw( yandex_app_id yandex_app_secret )) { 69 $self->{$_} = $config{$_} || $state->{session}->{$_} || return undef; 70 } 71 if ( exists $config{yandex_scope} && ref $config{yandex_scope} eq 'ARRAY' && scalar @{$config{yandex_scope}} ) { 72 $self->{yandex_scope} = join(' ', @{$config{yandex_scope}}); 73 } elsif ( scalar(@{$state->{session}{yandex_scope}}) ) { 74 $self->{yandex_scope} = join(' ', @{$state->{session}->{yandex_scope}}); 75 } 76 $self->{timeout} = $state->{session}->{connection_timeout} || 3; 77 for (qw(yandex_redirect_uri)) { 78 $self->{$_} = $config{$_} || $state->{session}->{$_}; 79 } 80 return $self; 81 } 82 83 sub authorize_url { 84 my $self = shift; 85 my (%args) = @_; 86 my $go = URI->new( $self->{yandex_authorize_url} ); 87 $go->query_param( response_type => 'code' ); 88 $go->query_param( client_id => $self->{yandex_app_id} ); 89 $go->query_param( scope => $self->{yandex_scope} || '' ); 90 $go->query_param( display => 'page' ); 91 $go->query_param( v => $self->{yandex_api_version} ); 92 $args{redirect_uri} ||= $self->{yandex_redirect_uri}; 93 for ( keys %args ) { 94 $go->query_param( $_ => $args{$_} ); 95 } 96 warn "YANDEX AUTH URL: $go\n" if $DEBUG; 97 my $local_session = $session || $keeper->{session}->get_session; 98 $local_session->set( yandex_redirect_url => $self->{yandex_redirect_uri} ); 99 return $go; 100 } 101 102 sub authenticate { 103 my ( $self, %authinfo ) = @_; 104 warn "YANDEX.authenticate" if $DEBUG; 105 106 my $local_session = $session || $keeper->{session}->get_session; 107 my $redirect_uri = $self->{yandex_redirect_uri}; 108 109 my $access_token = $local_session->{yandex_access_token}; 110 my $yandex_user_id = $local_session->{yandex_user_id}; 111 my $expires = $local_session->{yandex_expires}; 112 if ($access_token and $expires > time) { 113 warn "Already have access_token" if $DEBUG; 114 } else { 115 undef $access_token; 116 } 117 my $code = $authinfo{'code'}; 118 unless ( $code ) { 119 warn "Call to authenticate without code\n"; 120 return undef; 121 } 122 my $ua = LWP::UserAgent->new; 123 $ua->timeout($self->{timeout}); 124 125 unless ($access_token) { 126 my $content = 'grant_type=authorization_code&code='.$code 127 .'&client_id='.$self->{yandex_app_id} 128 .'&client_secret='.$self->{yandex_app_secret}; 129 my $req = HTTP::Request->new( 130 'POST', 131 $self->{yandex_access_token_url}, 132 [ 133 'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8', 134 'Content-Length' => length( $content ), 135 ], 136 $content, 137 ); 138 warn "Token request: [".Dumper($req)."]\n" if $DEBUG; 139 my $res = $ua->request($req); 140 unless ($res->code == 200) { 141 warn "YANDEX: Access_token request failed: ".$res->status_line."\n"; 142 return undef; 143 } 144 my $info = $JSON->decode($res->decoded_content); 145 warn Dumper $info if $DEBUG; 146 unless ( ref $info eq 'HASH' && ($access_token = $info->{access_token}) ) { 147 warn "No access token in response: ".$res->decoded_content."\n"; 148 return undef; 149 } 150 $local_session->set( yandex_access_token => $access_token ); 151 if ( my $expires = $info->{expires_in} ) { 152 $local_session->set( yandex_expires => time + $expires ); 153 } 154 warn "YANDEX: requested access token" if $DEBUG; 155 } else { 156 warn "YANDEX: have access token" if $DEBUG; 157 } 158 159 160 $ua->default_header( 'Authorization' => "OAuth ".$access_token ); 161 my $req = URI->new( $self->{yandex_user_info_url} ); 162 $req->query_param( format => 'json' ); 163 164 warn "YANDEX: Fetching user $req\n" if $DEBUG; 165 my $res = $ua->get($req); 166 unless ($res->code == 200) { 167 warn "YANDEX: user request failed: ".$res->status_line."\n"; 168 return undef; 169 } 170 171 my $user_info; 172 unless ( $user_info = eval { $JSON->decode($res->decoded_content) } ) { 173 warn "user '".$res->decoded_content."' decode failed: $@\n"; 174 return undef; 175 } 176 warn Dumper($user_info) if $DEBUG; 177 return undef unless exists $user_info->{client_id}; 178 179 foreach my $key ( qw(display_name last_name first_name real_name) ) { 180 $user_info->{$key} = Encode::encode('utf-8', $user_info->{$key}); 181 } 182 183 my @plugins = split (/[\ |\t]+/, $state->{plugins}); 184 my $name = $user_info->{first_name}.' '.$user_info->{last_name}; 185 my $email = exists $user_info->{default_email} && $user_info->{default_email} ? $user_info->{default_email} : undef; 186 if ( grep { $_ eq 'users' } @plugins ) { 187 my $user; 188 if ( $state->{users}->use_credentials ) { 189 if ( $local_session->id ) { 190 $user = $keeper->{users}->get_profile( id => $local_session->{id} ); 191 } else { 192 $user = $keeper->{users}->get_profile( yandex => $user_info->{psuid} ); 193 } 194 } 195 if ( !ref $user && ($email || exists $local_session->{email}) ) { 196 $user = $keeper->{users}->get_profile( email => $email || $local_session->{email} ); 197 } 198 unless ( ref $user ) { 199 $user = $keeper->{users}->get_profile( login => 'yandex:'.$user_info->{login} ); 200 } 201 unless ( ref $user ) { 202 my $user_class = $state->{users}->profile_document_class; 203 $user = $user_class->new( $keeper ); 204 my %props = map { $_->{attr} => $_ } $user->structure; 205 $user->login( $email || 'yandex:'.$user_info->{login} ); 206 $user->name( $user_info->{last_name}.', '.$user_info->{first_name} ); 207 $user->status( 1 ); 208 $user->type( 0 ); 209 $user->login_method('yandex'); 210 $user->email( $email ); 211 212 my ($prop_ava) = grep { $_->{attr} eq 'avatar' && $_->{type} eq 'image' } $user->structure; 213 if ( ref $prop_ava && !$user_info->{is_avatar_empty} ) { 214 my $avatar = $user->_store_image( get_avatar_url($user_info->{default_avatar_id}), attr => 'avatar' ); 215 $user->avatar( $user->_serialize($avatar) ); 216 } 217 218 $user->store; 219 } else { 220 my ($prop_ava) = grep { $_->{attr} eq 'avatar' && $_->{type} eq 'image' } $user->structure; 221 if ( ref $prop_ava ) { 222 my $avatar = $user->get_image( 'avatar' ); 223 if ( !(ref $avatar && exists $avatar->{filename}) && !$user_info->{is_avatar_empty} ) { 224 my $avatar = $user->_store_image( get_avatar_url($user_info->{default_avatar_id}), attr => 'avatar' ); 225 $user->avatar( $user->_serialize($avatar) ); 226 $user->store; 227 } 228 } 229 } 230 if ( $state->{users}->use_credentials ) { 231 $user->create_credential( 232 name => $user_info->{last_name}.', '.$user_info->{first_name}, 233 yandex => $user_info->{psuid}, 234 avatar => get_avatar_url($user_info->{default_avatar_id}), 235 ); 236 } 237 my %data = session::Keeper::_get_hash_from_profile( $user ); 238 $data{auth_by} = 'yandex'; 239 if ( !$user_info->{is_avatar_empty} ) { 240 $data{avatar} ||= get_avatar_url($user_info->{default_avatar_id}); 241 } 242 $local_session->set( %data ); 243 244 } else { 245 my %data = ( 246 id => $user_info->{psuid}, 247 name => $name, 248 login => $email || 'yandex:'.$user_info->{login}, 249 status => 1, 250 type => 0, 251 auth_by => 'yandex', 252 ltime => time, 253 ); 254 if ( !$user_info->{is_avatar_empty} ) { 255 $data{avatar} = get_avatar_url($user_info->{default_avatar_id}); 256 } 257 $local_session->set( %data ); 258 } 259 return $local_session; 260 } 261 262 sub get_avatar_url { 263 return undef unless @_ && @_[0]; 264 return 'https://avatars.mds.yandex.net/get-yapic/'.@_[0].'/islands-200'; 265 } 266 267 1; -
utf8/plugins/session/lib/session/Init.pm
8 8 use session::Session; 9 9 use session::AUTH::FaceBook; 10 10 use session::AUTH::VKontakte; 11 use session::AUTH::Yandex; 11 12 use session::AUTH::Mailru; 12 13 use session::AUTH::Google; 13 14 -
utf8/plugins/session/lib/session/State.pm.proto
75 75 $self->{vk_user_post_url} = '@VK_USER_POST_URL@'; 76 76 $self->{vk_scope} = '@VK_SCOPE@'; 77 77 78 $self->{yandex_app_id} = '@YANDEX_APP_ID@'; 79 $self->{yandex_app_secret} = '@YANDEX_APP_SECRET@'; 80 $self->{yandex_redirect_uri} = '@YANDEX_REDIRECT_URL@'; 81 $self->{yandex_scope} = [qw(@YANDEX_SCOPE@)]; 82 78 83 $self->{mailru_app_id} = '@MAILRU_APP_ID@'; 79 84 $self->{mailru_app_secret} = '@MAILRU_APP_SECRET@'; 80 85 $self->{mailru_redirect_uri} = '@MAILRU_REDIRECT_URL@';