Giter Site home page Giter Site logo

rxsocialconnect-android's Introduction

⚠️ Deprecated ⚠️

Use SocialConnect instead.

Android Arsenal

OAuth RxJava extension for Android. iOS version is located at this repository.

RxSocialConnect

RxSocialConnect simplifies the process of retrieving authorizations tokens from multiple social networks to a minimalist observable call, from any Fragment or Activity.

OAuth20Service facebookService = //...

RxSocialConnect.with(fragmentOrActivity, facebookService)
                    .subscribe(response -> response.targetUI().showResponse(response.token()));

Features:

  • Webview implementation to handle the sequent steps of oauth process.
  • Storage of tokens encrypted locally
  • Automatic refreshing tokens taking care of expiration date.
  • I/O operations performed on secondary threads and automatic sync with user interface on the main thread, thanks to RxAndroid
  • Mayor social network supported, more than 16 providers; including Facebook, Twitter, GooglePlus, LinkedIn and so on. Indeed, it supports as many providers as ScribeJava does, because RxSocialConnect is a reactive-android wrapper around it.
  • Honors the observable chain. RxOnActivityResult allows RxSocialConnect to transform every oauth process into an observable for a wonderful chaining process.

Setup

Add the JitPack repository in your build.gradle (top level module):

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

And add next dependencies in the build.gradle of android app module:

dependencies {
    compile 'com.github.VictorAlbertos.RxSocialConnect-Android:core:1.0.1-2.x'
    compile 'io.reactivex.rxjava2:rxjava:2.0.5'
}

Usage

Because RxSocialConnect uses RxActivityResult to deal with intent calls, all its requirements and features are inherited too.

Before attempting to use RxSocialConnect, you need to call RxSocialConnect.register in your Android Application class, supplying as parameter the current instance and an encryption key in order to save the tokens on disk encrypted, as long as an implementation of JSONConverter interface.

Because RxSocialConnect uses internally Jolyglot to save on disk the tokens retrieved, you need to add one of the next dependency to gradle.

dependencies {
    // To use Gson
    compile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.3'

    // To use Jackson
    compile 'com.github.VictorAlbertos.Jolyglot:jackson:0.0.3'

    // To use Moshi
    compile 'com.github.VictorAlbertos.Jolyglot:moshi:0.0.3'
}
public class SampleApp extends Application {

    @Override public void onCreate() {
        super.onCreate();

        RxSocialConnect.register(this, "myEncryptionKey")
            .using(new GsonSpeaker());
    }
}

Every feature RxSocialConnect exposes can be accessed from both, an activity or a fragment instance.

Limitation:: Your fragments need to extend from android.support.v4.app.Fragment instead of android.app.Fragment, otherwise they won't be notified.

The generic type of the observable returned by RxSocialConnect when subscribing to any of its providers is always an instance of Response class.

This instance holds a reference to the current Activity/Fragment, accessible calling targetUI() method. Because the original one may be recreated it would be unsafe calling it. Instead, you must call any method/variable of your Activity/Fragment from this instance encapsulated in the response instance.

Also, this instance holds a reference to the token.

Retrieving tokens using OAuth1.

On social networks which use OAuth1 protocol to authenticate users (such us Twitter), you need to build a OAuth10aService instance and pass it to RxSocialConnect.

OAuth10aService twitterService = new ServiceBuilder()
                .apiKey(consumerKey)
                .apiSecret(consumerSecret)
                .callback(callbackUrl)
                .build(TwitterApi.instance());

RxSocialConnect.with(fragmentOrActivity, twitterService)
                    .subscribe(response -> {
                        OAuth1AccessToken token = response.token();
                        response.targetUI().showToken(token.getToken());
                        response.targetUI().showToken(token.getTokenSecret());
                    });

Once the OAuth1 process has been successfully completed, you can retrieve the cached token calling RxSocialConnect.getTokenOAuth1(defaultApi10aClass) -where defaultApi10aClass is the provider class used on the oauth1 process.

        RxSocialConnect.getTokenOAuth1(TwitterApi.class)
                .subscribe(token -> showResponse(token),
                        error -> showError(error));

Retrieving tokens using OAuth2.

On social networks which use OAuth2 protocol to authenticate users (such us Facebook, Google+ or LinkedIn), you need to build a OAuth20Service instance and pass it to RxSocialConnect.

OAuth20Service facebookService = new ServiceBuilder()
                .apiKey(appId)
                .apiSecret(appSecret)
                .callback(callbackUrl)
                .scope("public_profile")
                .build(FacebookApi.instance());

RxSocialConnect.with(fragmentOrActivity, facebookService)
                    .subscribe(response -> {
                        OAuth2AccessToken token = response.token();
                        response.targetUI().showToken(token.getAccessToken());
                    });

Once the OAuth2 process has been successfully completed, you can retrieve the cached token calling RxSocialConnect.getTokenOAuth2(defaultApi20Class) -where defaultApi20Class is the provider class used on the oauth2 process.

        RxSocialConnect.getTokenOAuth2(FacebookApi.class)
                .subscribe(token -> showResponse(token),
                        error -> showError(error));

Token lifetime.

After retrieving the token, RxSocialConnect will save it on disk to return it on future calls without doing again the oauth process. This token only will be evicted from cache if it is a OAuth2AccessToken instance and its expiration time has been fulfilled.

But, if you need to close an specific connection (or delete the token from the disk for that matters), you can call RxSocialConnect.closeConnection(baseApiClass) at any time to evict the cached token -where baseApiClass is the provider class used on the oauth process.

//Facebook
RxSocialConnect.closeConnection(FacebookApi.class)
                .subscribe(_I ->  showToast("Facebook disconnected"));

//Twitter
RxSocialConnect.closeConnection(TwitterApi.class)
                .subscribe(_I ->  showToast("Twitter disconnected"));

You can also close all the connections at once, calling RxSocialConnect.closeConnections()

RxSocialConnect.closeConnections()
                .subscribe(_I ->  showToast("All disconnected"));

OkHttp interceptors.

RxSocialConnect can be powered with OkHttp (or Retrofit for that matters) to bypass authentication header configuration when dealing with specific endpoints. Using the interceptors provided by RxSocialConnect, it's a 0 configuration process to be able to reach any http resource from any api client (Facebook, Twitter, etc).

First of all, install RxSocialConnectInterceptors library using gradle:

dependencies {
    compile 'com.github.VictorAlbertos.RxSocialConnect-Android:okhttp_interceptors:1.0.1-2.x'
}

After you have retrieved a valid token -if you attempt to use these interceptors prior to retrieving a valid token a NotActiveTokenFoundException will be thrown, you can now use OAuth1Interceptor or OAuth2Interceptor classes to bypass the authentication headers configuration, depending on the OAuth version of your social network of interest.

OAuth1Interceptor.

OAuth10aService yahooService = //...

OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new OAuth1Interceptor(yahooService))
                .build();

//If using retrofit...
YahooApiRest yahooApiRest = new Retrofit.Builder()
        .baseUrl("")
        .client(client)
        .build().create(YahooApiRest.class);

OAuth2Interceptor.

OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new OAuth2Interceptor(FacebookApi.class))
                .build();

//If using retrofit...
FacebookApiRest facebookApiRest = new Retrofit.Builder()
        .baseUrl("")
        .client(client)
        .build().create(FacebookApiRest.class);

Now you are ready to perform any http call against any api in the same way you would do it for no OAuth apis.

Examples

  • Social networks connections examples can be found here.
  • OkHttp interceptors examples can be found here.

Proguard

-dontwarn javax.xml.bind.DatatypeConverter
-dontwarn org.apache.commons.codec.**
-dontwarn com.ning.http.client.**

keep class org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth1AccessToken {
    <fields>;
}
-keep class org.fuckboilerplate.rx_social_connect.internal.persistence.OAuth2AccessToken {
    <fields>;
}

Credits

Author

Víctor Albertos

Another author's libraries using RxJava:

  • RxCache: Reactive caching library for Android and Java.
  • Mockery: Android and Java library for mocking and testing networking layers with built-in support for Retrofit
  • RxActivityResult: A reactive-tiny-badass-vindictive library to break with the OnActivityResult implementation as it breaks the observables chain.
  • RxFcm: RxJava extension for Android Firebase Cloud Messaging (aka fcm).
  • RxPaparazzo: RxJava extension for Android to take images using camera and gallery.

rxsocialconnect-android's People

Contributors

cool04ek avatar hardwinder avatar miguelbcr avatar victoralbertos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rxsocialconnect-android's Issues

Document QueryString functionality

I just went down a rabbit hole of debugging that eventually led me to find that RxSocialConnect always assumes that the "oauth_verifier" parameter will be present.

If it's not present, it'll fail, even if the "oauth_token" parameter is present. This is the case on Goodreads - an example callback url from the api is "oauth://tir?oauth_token=xxxxxxxxxxxxx&authorize=1"

The solution for me was to replace the StrategyOAuth1 with a custom parser, which seems to be working fine, but it's quite non-intuitive. Maybe some documentation of this hidden feature is in order, assuming I have the facts straight.

For anyone else having the same problem, here's what my code looks like:

        QueryString.PARSER.replaceStrategyOAuth1(object : QueryStringStrategy {
            override fun extractCode(uri: Uri): String {
                return uri.getQueryParameter("oauth_token")
            }

            override fun extractError(uri: Uri): String? {
                return uri.getQueryParameter("error")
            }

        val goodReadsService = ServiceBuilder()
                .apiKey("xxxxxxxxxxxxxxxxxxxx")
                .apiSecret("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
                .callback(GoodreadsApi.CALLBACK_URI)
                .build(GoodreadsApi())

        RxSocialConnect.with(activity, goodReadsService)
                .subscribe({ response ->
                    TimberKt.d { response.token().token }
                }, { error ->
                    TimberKt.e(error, { "Couldn't get token!" })
                })

Oh, and thank you for this lib, it is awesome.

Activity Connect bug

Hi, thank you for this awesome library. I found it very useful. However, I have encountered an unpleasant bug I would like to report.
When you start ActivityConnect and then close it before webview has loaded you will get NPE in this line
if (!url.startsWith(service.callbackUrl())) return super.shouldOverrideUrlLoading(view, url);
because activity is already closed and service is null.
I can provide PR with fix as well.

Code extraction problem

Hi, Victor. I found simple but painful problem with extracting code from uri in that case
https://redirect_url#code=123456(VK OAuth2). Problem in #. Line String code = uri.getQueryParameter("code"); in rx_social_connect.internal.services.OAuth2Service returns null. I just copy-paste RxSocialConnect and add new method

public static <F extends Fragment> Observable<Response<F, com.github.scribejava.core.model.OAuth2AccessToken>> with(
            F fragment,
            OAuth20Service oAuth20Service,
            Service<OAuth2AccessToken, OAuth20Service> tokenService) {
        return startActivity(
                fragment,
                tokenService,
                oAuth20Service.getApi().getClass().getSimpleName(),
                OAuth2AccessToken.class)
                .map(new Func1<Response<Object, OAuth2AccessToken>, Response<F, com.github.scribejava.core.model.OAuth2AccessToken>>() {
                    @Override public Response<F, com.github.scribejava.core.model.OAuth2AccessToken> call(Response<Object, OAuth2AccessToken> response) {
                        return new Response(response.targetUI(), response.token());
                    }
                });
    }

that allow pass own rx_social_connect.internal.services.Service implementation to handle non-standart uri and correctly extract code. Can you add something like that in library core?

P.S. Sorry for my English :)

JSON parsing

Sorry if this is a dumb question, it's my first time trying this and I can't solve it.
I'm really new to Oauth2 and JSON so I'm using RxSocialConnect-Android library to simplify the OAuth2 process that requires Fitbit and to get some weight data. I followed this example. The response I get is this one:

{ weight=[ { bmi=21.0, date=2016-12-09, fat=14.059000015258789, logId=1.xxxxxxx, source=Aria, time=11:58:24, weight=68.0 }, { bmi=21.83, date=2016-12-14, logId=1.xxxxxxxx, source=Aria, time=14:31:39, weight=70.7 } ] }

I want to get just the "weight" and "date" parameters inside weight array. I have tried creating a pojo class following this example and replacing it by the "Object" field in my interface:

interface FitbitApiRest { String URL_BASE = "https://api.fitbit.com"; @GET("myrequest.json") Observable<Object>getData(); }

But I still can't get the parameters I want, just got something like "[com.myPackage.MyPojo@xxxxx",com.myPackage.MyPojo@yyyyy]"

What am I doing wrong?

Unnable to create session file after closing connections

I get this error when I try to login after calling RxSocialConnect.closeConnections() :

java.io.FileNotFoundException: /data/user/0/com.my.app/files/RxSocialConnect/FacebookApi: open failed: ENOENT (No such file or directory) on Disk.java

I've been debuging and these are my conclusions;

  • The first time the app is launched and RxSocialConnect.register() the cacheDirectory is created, so the session file (FacebookApi) in this case is created.
  • But if I do logout in my app and I call to RxSocialConnect.closeConnections() the cacheDirectory is deleted, so if I try login again the cacheDirectory is not created because RxSocialConnect.register() is not called anymore unless I destroy the app and launch it again.

So, as a possible solution, you could call cacheDirectory.mkdirs(); before the file creation

What do you think?
Thanks!

Handle tokens without expiration date

Some OAuth providers (such as Github) don't specify a date for the expiration's token. For that reason, the class OAuth2AccessToken throws a NP when it tries to access the value of getExpiresIn method.

Related with #17

Add OkHttp interceptors

Add OkHttp Interceptors to handle authentication api calls for mayor social networks in order to access endpoint which require user authentication.

Add Proguard Config to Readme

I needed to add:

-dontwarn javax.xml.bind.DatatypeConverter
-dontwarn org.apache.commons.codec.**
-dontwarn com.ning.http.client.**

in order for the library to work with proguard.

How do you refresh the token?

public Observable<T> get(String keyToken, Class<T> classToken) {
        T response = retrieve(keyToken, classToken);

        if (response != null) {
            if (response instanceof OAuth2AccessToken) {
                if (!((OAuth2AccessToken)response).isExpired()) {
                    return Observable.just(response);
                }
            } else {
                return Observable.just(response);
            }
        }

        return null;
    }

Add a memory layer to persistence

To alleviate the time required to retrieve cached tokens from disk, a simple memory layer needs to be implemented.

This will be helpful when using getToken to configure headers prior to perform http calls with authentication requirements.

Screen Orientation

Hi. I would like to request a feature, if it aint present in lib now.

Can I explicitly set up screen orientation for ActivityConnect? So it will be for example portrait all the time?
If no, would you provide such in a future? I would be glad to help with PR.

Yahoo Oauth issue - Cycle Prohibited

Hi there,

Thanks for your great library!!
I'm having a problem with Yahoo oauth code.
The webview is displaying with a message:
Description: Could not process your request for the document because it would cause an HTTP proxy cycle. Please check the URL and your browser's proxy settings.

Please, any help?

Thanks in advance.

Add accessors method to retrieve cached token without calling connect

Sometimes it may be required to retrieve the cached token directly without calling RxSocialConnect.with(fragmentOrActivity, apiService).

Some potential scenario would be when you need to retrieve the token or throw an exception, because at this point of the program flow it is not possible to open the workflow of the OAath authentication process.

Memory layer error

When retrieving token from getToken() if connect() has not been call first, the token is always retrieved from disk

Disk caching does not work

To reproduce, simply run the demo app. Sign in to any service (I'm using oauth 1 and twitter, haven't tried oauth 2) and get a valid token.

Now, quit the app entirely, reopen it, and try to get the token.

It won't work - something seems to be going wrong with the encryption/decryption but I don't know what. Unit tests are all passing. Tested on both emulator and real device.

cc @miguelbcr

Extract Gson from dependencies

Disk.java uses Gson for persistence. But some could use another JSON-converters, such as Jackson, LoganSquare etc. and it would be another dependency and increased pressure on DEX-limit.
Try to extract these converter as an interface with the ability to provide JSON-converter when registering RxSocialConnect in Application. For example look at Retrofit when you provide instance of Converter when building Retrofit. This way people who use another JSON-converters could use their own converters with your library

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.