How to Implement Social Ally as an API


#1

as of now, I have a frontend social authentication, and want to use the ally if they are allow to access via restful api ? meaning, how can I can I get the authenticated User object ?
Thanks


#2

Currently not exactly possible… But it will be soon…

Read here:

Also waiting for this… If you need it right now and can’t wait for update, I can share my monkey patch for this issue :slight_smile:


#3

sure that could help a lot and share to the entire devs :slight_smile:


#4

Ok, here you go :slight_smile:

It’s pretty simple actually… But this is not a real solution just a temporary way to enable social auth via for example iOS app accessing your REST API. I would wait for official update of Ally provider if I could wait :slight_smile:

Inside node_modules/@adonisjs/ally/Drivers/WHATEVER.js (let’s use Facebook.js as example). Change getUser method:

async getUser(queryParams, fields) {
    const code = queryParams.code
    let accessToken = queryParams.accessToken // add this

    /**
     * Throw an exception when query string does not have
     * code.
     */
    if (!code && !accessToken) { // introduce accessToken check
        const errorMessage = this.parseRedirectError(queryParams)
        throw CE.OAuthException.tokenExchangeException(errorMessage, null, errorMessage)
    }
    
    if(!accessToken) { // change accessToken retrival to check if we already have accessToken
        const accessTokenResponse = await this.getAccessToken(code, this._redirectUri, {
            grant_type: 'authorization_code'
        })
        accessToken = accessTokenResponse.accessToken
    }

    // finally, just send access token that you got via your API or FB Api
    const userProfile = await this._getUserProfile(accessToken, fields)

    // ***** THATS IT... NO NEED TO CHANGE ANYTHING ELSE *****
    
    const user = new AllyUser()
    const avatarUrl = `${this.baseUrl}/${userProfile.id}/picture?type=normal`

    /**
     * Build user
     */
    user
        .setOriginal(userProfile)
        .setFields(
            userProfile.id,
            userProfile.name,
            userProfile.email,
            userProfile.name,
            avatarUrl
        )
        .setToken(
            accessTokenResponse.accessToken,
            accessTokenResponse.refreshToken,
            null,
            Number(_.get(accessTokenResponse, 'result.expires'))
        )

    return user
}

So, now when for example iOS app gets access token via Facebook iOS SDK, it will contact your REST API sending accessToken instead of code param!