All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.neovisionaries.android.oauth20.OAuth20ViewClient Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2014 Neo Visionaries Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.neovisionaries.android.oauth20;


import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.webkit.WebView;
import android.webkit.WebViewClient;


/**
 * A {@link WebViewClient} for {@link OAuth20View}.
 *
 * @since 1.9
 *
 * @author Takahiko Kawasaki
 */
class OAuth20ViewClient extends WebViewClient
{
    private final OAuth20View mOAuth20View;
    private final AuthorizationRequest mRequest;
    private final ResponseType mResponseType;
    private final String mRedirectUri;
    private final OAuth20ViewListener mListener;


    OAuth20ViewClient(OAuth20View view, AuthorizationRequest request, OAuth20ViewListener listener)
    {
        mOAuth20View  = view;
        mRequest      = request;
        mResponseType = request.getResponseType();
        mRedirectUri  = (request.getRedirectUri() == null) ? null
                      : request.getRedirectUri().toString();
        mListener     = listener;
    }


    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url)
    {
        process(url);

        return super.shouldOverrideUrlLoading(view, url);
    }


    private void process(String url)
    {
        // If a redirect URI has been specified explicitly and
        // the URL does not match the redirect URI.
        if (mRedirectUri != null && url.startsWith(mRedirectUri) == false)
        {
            // The URL does not contain a response from the
            // authorization endpoint.
            return;
        }

        URL target;

        try
        {
            // Convert String to URL.
            target = new URL(url);
        }
        catch (MalformedURLException e)
        {
            // This should not happen.
            return;
        }

        if (mResponseType == ResponseType.code)
        {
            // A response from the authorization endpoint includes
            // parameters in the query component.
            processCode(target.getQuery());
        }
        else
        {
            // A response from the authorization endpoint includes
            // parameters in the fragment component.
            processToken(target.getRef());
        }
    }


    private void processCode(String query)
    {
        if (query == null)
        {
            return;
        }

        Map> parameters = parseParameters(query);

        if (parameters.containsKey("code"))
        {
            fireCodeIssued(parameters);
        }
        else if (parameters.containsKey("error"))
        {
            fireError(parameters);
        }
    }


    private void processToken(String fragment)
    {
        if (fragment == null)
        {
            return;
        }

        Map> parameters = parseParameters(fragment);

        if (parameters.containsKey("access_token"))
        {
            fireTokenIssued(parameters);
        }
        else if (parameters.containsKey("error"))
        {
            fireError(parameters);
        }
    }


    private Map> parseParameters(String input)
    {
        Map> parameters = new HashMap>();

        for (String parameter : input.split("&"))
        {
            String[] pair = parameter.split("=", 2);

            if (pair == null || pair.length == 0 || pair[0].length() == 0)
            {
                continue;
            }

            String key   = urlDecode(pair[0]);
            String value = (pair.length == 2) ? urlDecode(pair[1]) : "";

            List list = parameters.get(key);

            if (list == null)
            {
                list = new ArrayList();
                parameters.put(key, list);
            }

            list.add(value);
        }

        return parameters;
    }


    private String urlDecode(String input)
    {
        try
        {
            return URLDecoder.decode(input, "UTF-8");
        }
        catch (UnsupportedEncodingException e)
        {
            // This never happens.
            return input;
        }
    }


    private String getParameter(Map> parameters, String name)
    {
        List list = parameters.get(name);

        if (list == null || list.size() == 0)
        {
            return null;
        }

        return list.get(0);
    }


    private int getParameterAsInt(Map> parameters, String name)
    {
        String value = getParameter(parameters, name);

        if (value == null)
        {
            return 0;
        }

        try
        {
            return Integer.parseInt(value);
        }
        catch (NumberFormatException e)
        {
            return 0;
        }
    }


    private OAuth20Error getParameterError(Map> parameters)
    {
        String value = getParameter(parameters, "error");

        if (value == null)
        {
            return null;
        }

        try
        {
            // Convert String to OAuth20Error.
            return OAuth20Error.valueOf(value);
        }
        catch (Exception e)
        {
            // Unknown error. The OAuth 2.0 authorization endpoint
            // does not comply with the specification.
            return null;
        }
    }


    private void fireCodeIssued(Map> parameters)
    {
        String code  = getParameter(parameters, "code");
        String state = getParameter(parameters, "state");

        try
        {
            mListener.onCodeIssued(mOAuth20View, mRequest, code, state);
        }
        catch (Throwable t)
        {
            // Ignore.
        }
    }


    private void fireTokenIssued(Map> parameters)
    {
        String accessToken = getParameter(parameters, "access_token");
        String tokenType   = getParameter(parameters, "token_type");
        int expiresIn      = getParameterAsInt(parameters, "expires_in");
        String scope       = getParameter(parameters, "scope");
        String state       = getParameter(parameters, "state");

        AccessToken ac = new AccessToken()
            .setAccessToken(accessToken)
            .setTokenType(tokenType)
            .setExpiresIn(expiresIn)
            .setScope(scope)
            ;

        try
        {
            mListener.onTokenIssued(mOAuth20View, mRequest, ac, state);
        }
        catch (Throwable t)
        {
            // Ignore.
        }
    }


    private void fireError(Map> parameters)
    {
        OAuth20Error error = getParameterError(parameters);
        String description = getParameter(parameters, "error_description");
        String uri         = getParameter(parameters, "error_uri");
        String state       = getParameter(parameters, "state");

        try
        {
            mListener.onError(mOAuth20View, mRequest, error, description, uri, state);
        }
        catch (Throwable t)
        {
            // Ignore.
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy