Как да извлека допълнителна информация на потребителя от услугите на Azure Mobile/App?

Трябва да получа допълнителна информация за потребителя от социални акаунти като Facebook и Google+. Когато за първи път прочетох за мобилните услуги на Azure, си помислих, че това е светият граал на социалното удостоверяване. Е, след цяла седмица скубане на косата започвам да преосмислям първото си впечатление. Той се удостоверява толкова лесно, колкото би могъл да направи. Конфигурирах Google+ и FB да работят с Azure, конфигурирах Azure да използва ключа/тайната от всеки доставчик и всичко просто проработи. Успях да вляза перфектно. Проблемът започна, когато се опитах да получа информация от регистрирания потребител, което честно казано смятам за основно!

Мобилните услуги на Azure връщат UserId и Token, които не можете да използвате, за да поискате допълнителна информация за избрания доставчик. Така че дори и да създам втора заявка, използвайки например графичния API на FB, това няма да работи (опитах!). Този токен е собствен токен на Azure. Така че разбрах от няколко публикации на Карлос Фигейра (SE в Azure), че трябва да персонализирам моя скрипт на Azure, да направя заявка до Azure и след това ще мога да го накарам да работи.

Също така прочетох няколко публикации от Carlos Figueira за това как да внедря тази допълнителна функционалност и въпреки че това не беше това, което търсех (персонализиране на сървъра), реших да работя с това. Но моят тип на връщане е MobileServiceUser и този тип има само 2 свойства: UserId и MobileServiceAuthenticationToken. Така че дори след като добавих сървърния скрипт от Карлос, не можах да извлека допълнителната информация от моето приложение Xamarin.

Прочетох много неща, проучих много и не можах да намеря отговор =/ Между другото това не е отговорът: Как да получа потребителско име, имейл и т.н. от MobileServiceUser?

Някой успя ли да го накара да работи?

PS: Не публикувам никакъв код тук, защото работи. Ако смятате, че проверката на част от моя код ще помогне за дешифрирането на проблема, просто ме уведомете.

Благодаря предварително!

РЕДАКТИРАНЕ:

Скрипт

function insert(item, user, request) {
    item.UserName = "<unknown>"; // default
    user.getIdentities({
        success: function (identities) {
            var url = null;
            var oauth = null;
            if (identities.google) {
                var googleAccessToken = identities.google.accessToken;
                url = 'https://www.googleapis.com/oauth2/v3/userinfo?access_token=' + googleAccessToken;
            } else if (identities.facebook) {
                var fbAccessToken = identities.facebook.accessToken;
                url = 'https://graph.facebook.com/me?access_token=' + fbAccessToken;
            } else if (identities.microsoft) {
                var liveAccessToken = identities.microsoft.accessToken;
                url = 'https://apis.live.net/v5.0/me/?method=GET&access_token=' + liveAccessToken;
            } else if (identities.twitter) {
                var userId = user.userId;
                var twitterId = userId.substring(userId.indexOf(':') + 1);
                url = 'https://api.twitter.com/1.1/users/show.json?user_id=' + twitterId;
                var consumerKey = process.env.MS_TwitterConsumerKey;
                var consumerSecret = process.env.MS_TwitterConsumerSecret;
                oauth = {
                    consumer_key: consumerKey,
                    consumer_secret: consumerSecret,
                    token: identities.twitter.accessToken,
                    token_secret: identities.twitter.accessTokenSecret
                };
            }

            if (url) {
                var requestCallback = function (err, resp, body) {
                    if (err || resp.statusCode !== 200) {
                        console.error('Error sending data to the provider: ', err);
                        request.respond(statusCodes.INTERNAL_SERVER_ERROR, body);
                    } else {
                        try {
                            var userData = JSON.parse(body);
                            item.UserName = userData.name;
                            request.execute();
                        } catch (ex) {
                            console.error('Error parsing response from the provider API: ', ex);
                            request.respond(statusCodes.INTERNAL_SERVER_ERROR, ex);
                        }
                    }
                }
                var req = require('request');
                var reqOptions = {
                    uri: url,
                    headers: { Accept: "application/json" }
                };
                if (oauth) {
                    reqOptions.oauth = oauth;
                }
                req(reqOptions, requestCallback);
            } else {
                // Insert with default user name
                request.execute();
            }
        }
    });
}

person eestein    schedule 03.07.2015    source източник


Отговори (2)


Говорите за токена от страна на клиента, нали? Този токен е специфичен само за клиента. Ако използвате сървърния поток, сървърът е единственият с този токен. Ако искате да изпратите това на клиента, трябва да го направите чрез персонализиран API, който създавате.

Този клас, за който говорите, съдържа само тези два имота. Но от страна на вашия сървър, вашият ServiceUser може да има достъп до различните токени на доставчик на самоличност, за да говори с API на тези сървъри. Вашата свързана публикация е правилна по отношение на начина, по който осъществявате достъп до токена, грешите къде можете да получите достъп до този токен, това е само от страната на сървъра (ако използвате насочения към сървъра поток за влизане).

person Chris Anderson-MSFT    schedule 04.07.2015
comment
Мисля, че сте прочели нещо погрешно... Вашата свързана публикация е правилна по отношение на начина, по който осъществявате достъп до токена Знам, затова казах By the way this is not the answer. грешите къде можете да получите достъп до този токен, това е само от страната на сървъра Знам, затова казах So even if I were to create a second request using FB's graph API for instance, that wouldn't work (I've tried!). That token is Azure's own token. Дори и да използвам потока за влизане в сървъра (което казах в публикацията си, имам), пак не мога да получа тази информация, защото класът (да, този, който сте свързали) не ми позволява. Благодаря за отделеното време. - person eestein; 04.07.2015
comment
Така че сървърът има действителния IDP токен. Така че от страната на сървъра можете да използвате самоличността ServiceUser, за да вземете правилния токен за достъп до API на IDP. Ето още един пример, когато те бяха малко объркани от това и го разбраха. stackoverflow .com/questions/25463125/ Класът, който свързах, и класът, от който се опитвахте да извадите токена, НЯМА IDP токена, той има само MobileService ID. Вероятно ще искате просто да извлечете данните от страната на сървъра, като използвате метода в свързаните публикации. - person Chris Anderson-MSFT; 04.07.2015
comment
Добре, опитвах се да ти кажа, че знам и го опитах. Не казвам, че го направих правилно, но го опитах. Също така моят бекенд е JS, а не .NET, така че не знам дали решението би било същото, нали? Тъй като работите в @MS, вероятно сте запознати с Карлос Фигейра... както казах в публикацията си, следвах неговите уроци за JS бекенда, но отново, не казвам, че грешката не е от моя страна... просто казвам, че не не изглежда, че информацията за настоящия сценарий е лесно достъпна. Ако можете да предоставите допълнителна информация за това, ще съм благодарен. - person eestein; 04.07.2015
comment
Да, същото понятие за бекенда на JS. Бихте ли обмислили да споделите своя бекенд код, където се опитвате да получите достъп до IDP токена на потребителя? Мога да опитам да погледна, ако нещо изглежда неправилно конфигурирано. - person Chris Anderson-MSFT; 04.07.2015
comment
Разбира се, просто проверете моя актуализиран въпрос. Но както казах, проблемът е, че дори да успея да върна тази информация, класът MobileServiceUser няма да ми позволи да видя тези свойства, защото има само две свойства. Благодаря. - person eestein; 04.07.2015
comment
да Това винаги ще е така. Имате нужда от клиентски API или таблица, както предлага Карлос в края на своя блог, която ви връща тази информация. MobileServiceUser никога няма да изложи директно тази информация. Трябва сам да разкриеш това. - person Chris Anderson-MSFT; 04.07.2015
comment
Добре, след този код, който ви показах, какво още трябва да направя? Благодаря. - person eestein; 04.07.2015
comment
Използвайте последния раздел от блога на Карлос. blogs.msdn.com/b/carlosfigueira/archive/2012/10/25/ Основно създавате таблица с идентичности, която се синхронизира с вашето устройство. - person Chris Anderson-MSFT; 04.07.2015
comment
Крис, оценявам вашето време и тъй като изглежда, че няма по-добро решение/отговор в момента, решавам дали да се занимавам с тази прекомерна допълнителна работа или просто да премина към обикновена реализация на oAuth. Все още мисля, че трябваше да внедрите това по подразбиране! Разбирам опасенията за сигурността, свързани с транзакциите, използващи токена за достъп, но не би трябвало да е толкова трудно да се получи тази информация. Благодаря отново. - person eestein; 05.07.2015
comment
Благодаря за обратната връзка. Работим, за да направим изживяването с удостоверяване по-добро за следващата ни итерация. Изглежда, че удостоверяването от страна на клиента може да е повече от това, което очаквате, тъй като искате токена от страна на клиента. Бих предложил да разгледате това, ако не искате да създадете API от страна на сървъра, за да извлечете самоличностите. Кажете ми, ако имате други проблеми: [email protected] - person Chris Anderson-MSFT; 05.07.2015
comment
Крис, не бих искал, нито имам нужда от токена, ако решението на Azure приеме заявка за обхват като тези променливи за обхват MS_*** и върне тези данни на клиента, като имейл. Мисля, че това е доста основна информация за предоставяне, дори ако беше по заявка, както споменах, чрез създаване на променливите MS_*** в Azure. Наистина трябва да го обмислите, ако не е в текущите ви планове. Нуждата е ясна, просто проверете всички тези колеги разработчици, които питат как да получат тази информация от Azure... Благодаря. - person eestein; 06.07.2015
comment
За съжаление, нещата леко се промениха от Azure Mobile Service към Azure Mobile Apps. Имах скрипт, подобен на оригиналния, публикуван в тази тема, който работеше с мобилни услуги, за да получи потребителския профил за всеки метод за удостоверяване. Процесът е подобен с мобилните приложения на Azure в смисъл, че удостоверявате чрез Google, Twitter и т.н. от страна на клиента, след което извиквате персонализиран API в мобилното приложение, за да извлечете действителната информация за профила. Липсва обаче документацията къде са някои от променливите на средата. - person James Quick; 03.02.2016
comment
Продължете и създайте въпрос, ако нещата не са ясни в мобилните приложения. Нашият екип следи за въпроси и ще направим всичко възможно, за да помогнем. - person Chris Anderson-MSFT; 05.02.2016

Ето персонализирания API скрипт, който работех в Mobile Services, за да върна профила на влезлия потребител. Работя върху актуализирането до мобилни приложения, тъй като някои променливи на средата изглежда са се променили. Ще се радвам да знам дали някой го е накарал да работи с мобилни приложения.

exports.get = function (request, response) {
var user = request.user;
user.getIdentities({
    success: function (identities) {
        var req = require('request');
        var url = null;
        var oauth = null;
        var userId = user.userId.split(':')[1];
        console.log('Identities: ', identities);
        if (identities.facebook) {
            url = 'https://graph.facebook.com/me?access_token=' +
                identities.facebook.accessToken;
        } else if (identities.google) {
            url = 'https://www.googleapis.com/oauth2/v3/userinfo' +
                '?access_token=' + identities.google.accessToken;
        } else if (identities.microsoft) {
            url = 'https://apis.live.net/v5.0/me?access_token=' +
                identities.microsoft.accessToken;
        } else if (identities.twitter) {
            var consumerKey = process.env.MS_TwitterConsumerKey;
            var consumerSecret = process.env.MS_TwitterConsumerSecret;
            oauth = {
                consumer_key: consumerKey,
                consumer_secret: consumerSecret,
                token: identities.twitter.accessToken,
                token_secret: identities.twitter.accessTokenSecret
            };
            url = 'https://api.twitter.com/1.1/users/show.json?' +
                'user_id=' + userId + '&include_entities=false';
        } else {
            response.send(500, { error: 'No known identities' });
            return;
        }

        if (url) {
            var reqParams = { uri: url, headers: { Accept: 'application/json' } };
            if (oauth) {
                reqParams.oauth = oauth;
            }
            req.get(reqParams, function (err, resp, body) {
                if (err) {
                    console.error('Error calling provider: ', err);
                    response.send(500, { error: 'Error calling provider' });
                    return;
                }

                if (resp.statusCode !== 200) {
                    console.error('Provider call did not return success: ', resp.statusCode);
                    response.send(500, { error: 'Provider call did not return success: ' + resp.statusCode });
                    return;
                }

                try {
                    var userData = JSON.parse(body);
                    response.send(200, userData);
                } catch (ex) {
                    console.error('Error parsing response: ', ex);
                    response.send(500, { error: ex });
                }
            });
        } else {
            response.send(500, { error: 'Not implemented yet', env: process.env });
        }
    }
});

};

person James Quick    schedule 03.02.2016
comment
Така че Azure UserId включва accesstoken на доставчика (facebook), правилно ли е? - person Emil; 10.11.2017