adonis6_ally_yandex
Version:
AdonisJS 6 Ally Yandex Driver
159 lines (158 loc) • 5.01 kB
JavaScript
/*
|--------------------------------------------------------------------------
| Ally Yandex Oauth driver
|--------------------------------------------------------------------------
|
| This is an Ally Oauth driver for authenticating users via Yandex.
|
*/
import { Exception } from '@poppinss/utils';
import { Oauth2Driver } from '@adonisjs/ally';
/**
* Yandex driver to login user via Yandex
*/
export class YandexDriver extends Oauth2Driver {
config;
accessTokenUrl = 'https://oauth.yandex.ru/token';
authorizeUrl = 'https://oauth.yandex.ru/authorize';
userInfoUrl = 'https://login.yandex.ru/info';
userAvatarUrl = 'https://avatars.yandex.net/get-yapic';
userAvatarSize = 'islands-200';
/**
* The param name for the authorization code
*/
codeParamName = 'code';
/**
* The param name for the error
*/
errorParamName = 'error';
/**
* Cookie name for storing the "yandex_oauth_state"
*/
stateCookieName = 'yandex_oauth_state';
/**
* Parameter name to be used for sending and receiving the state
* from yandex
*/
stateParamName = 'state';
/**
* Parameter name for defining the scopes
*/
scopeParamName = 'scope';
/**
* Scopes separator
*/
scopesSeparator = ' ';
constructor(ctx, config) {
super(ctx, config);
this.config = config;
/**
* Extremely important to call the following method to clear the
* state set by the redirect request
*/
this.loadState();
}
/**
* Configuring the redirect request with defaults
*/
configureRedirectRequest(request) {
/**
* Define user defined scopes or the default one's
*/
request.scopes(this.config.scopes || ['login:email', 'login:info', 'login:avatar']);
/**
* Set "response_type" param
*/
request.param('response_type', 'code');
}
/**
* Returns the HTTP request with the authorization header set
*/
getAuthenticatedRequest(url, token) {
const request = this.httpClient(url);
request.header('Authorization', `OAuth ${token}`);
request.header('Accept', 'application/json');
request.parseAs('json');
return request;
}
/**
* Fetches the user info from the Yandex API
*/
async getUserInfo(token, callback) {
const url = this.config.userInfoUrl || this.userInfoUrl;
const userAvatarUrl = this.config.userAvatarUrl || this.userAvatarUrl;
const userAvatarSize = this.config.userAvatarSize || this.userAvatarSize;
const request = this.getAuthenticatedRequest(url, token);
if (typeof callback === 'function') {
callback(request);
}
const body = await request.get();
const avatarUrl = `${userAvatarUrl}/${body.default_avatar_id}/${userAvatarSize}`;
return {
id: body.id,
nickName: body.login,
name: body.real_name,
avatarUrl: body.default_avatar_id ? avatarUrl : '',
original: body,
};
}
/**
* Fetches the user email from the Yandex API
*/
async getUserEmail(token, callback) {
const url = this.config.userInfoUrl || this.userInfoUrl;
const request = this.getAuthenticatedRequest(url, token);
if (typeof callback === 'function') {
callback(request);
}
const body = await request.get();
if (!body.default_email) {
throw new Exception('Cannot request user email. Make sure you are using the "login:email" scope');
}
return body.default_email;
}
/**
* Find if the current error code is for access denied
*/
accessDenied() {
const error = this.getError();
if (!error) {
return false;
}
return error === 'access_denied';
}
/**
* Returns details for the authorized user
*/
async user(callback) {
const token = await this.accessToken(callback);
const user = await this.getUserInfo(token.token, callback);
const email = await this.getUserEmail(token.token, callback);
return {
...user,
email: email,
emailVerificationState: 'unsupported',
token: token,
};
}
/**
* Finds the user by the access token
*/
async userFromToken(token, callback) {
const user = await this.getUserInfo(token, callback);
const email = await this.getUserEmail(token, callback);
return {
...user,
email: email,
emailVerificationState: 'unsupported',
token: { token, type: 'bearer' },
};
}
}
/**
* The factory function to reference the driver implementation
* inside the "config/ally.ts" file.
*/
export function YandexDriverService(config) {
return (ctx) => new YandexDriver(ctx, config);
}