Android SSO Okta 集成示例 [英] Android SSO Okta Integration Example

查看:74
本文介绍了Android SSO Okta 集成示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不太了解 Okta 和 Android.有谁知道一个很好的教程,它展示了如何将 android 应用程序连接到 Okta 框架中.或者我是否实施了 SAML SSO 实施,然后 Okta 与之相关联?任何代码示例都值得赞赏 - 特别是一个展示通用 SSO 的 Android 实现的代码示例(如果存在这种情况).

Don't know a lot about Okta and Android. Does anyone know of a good tutorial which shows how to wire an android application into the Okta framework. Or do I implement a SAML SSO implementation and then Okta is associated to that? Any code examples appreciated - especially one showing Android implementation of generic SSO, if such a thing exists.

推荐答案

好的,这里有很多地方要介绍,还有一些我没有做的工作.但基本思想是,在服务器端(我们使用 .Net),我们使用kentor"创建了一个 SAML 通信层.我没有使用这个,但想法是软件为 SSO(例如 Okta)与客户端的身份提供者 (IDP) 进行通信.IDP 客户端通常必须提供包含安全信息和最终 URL 的 XML 元数据,然后您向他们提供您的 SSO xml 元数据(抱歉,我没有在这部分工作!).

OK, alot of ground to cover here and some of the work I did not do. But the basic idea is that on the server side (we use .Net) we created a SAML communication layer using "kentor". I did not work with this, but idea is software communicating the the client's Identity Provider (IDP) for SSO (Okta for example). The IDP client usually has to provide XML meta data which has security info and ultimately a URL, and you provide them with your SSO xml meta data (sorry, I did not work on that part!).

基本上从那里开始,它在 Android 方面非常简单.最重要的是,上述交互会生成 SSO 客户端提供的 url,您将在 Android 端使用该 url 创建 webview,这将允许他们输入登录信息进行验证.

Basically from there it is pretty straight forward on the Android side. The bottom line is that the above interaction results in a url that the SSO client provides that you will use on the Android side to create a webview, which will allow them to enter their login information for verification.

我们对 URL 进行了硬编码,因为我们专门为客户创建了一个白标产品(您将在下面看到它为 Constants.SINGLE_SIGNON_URL),但是没有什么可以阻止您在之后将 URL 传回客户传递了 SSO 的组织代码(我们现在正在处理).换句话说,您存储 URL 或根据哪个客户生成 URL,然后在设备向您传递组织代码时返回该 URL.该 URL 实际上指向您的服务器,它重定向到 SSO 的 IDP (Okta) 登录页面.这是因为来自 OKTA 的响应需要发送到您的服务器,最终它将通过重定向发送回您的 webview.然后我们使用 cookie 存储生成的用户名,以允许正常的登录过程.可能有很多不同的方法来做到这一点,Okta 甚至提供了原生移动设备功能,但客户必须支持这一点.

We have the URL hardcoded since we create a white label product specifically for the customer (you will see that as Constants.SINGLE_SIGNON_URL below) but there is nothing that stops you from passing the URL back after a customer passes a Organization Code for SSO in (we are working on that now). In other words you store the URL or generate the URL based on which customer and then return that when the device passes you an Organizatioal Code. The URL is actually to your server, which redirects to the IDP (Okta) login page for SSO. This is because the response from OKTA needs to go to your server where ultimately it will be sent back by redirect to your webview. We used the cookies to then store the resulting username to allow the normal login process. Probably a lot of different ways to do that, and Okta even provides a native mobile device capability, but the customer has to support that.

这是一张图表,希望能阐明其中的一些高级部分:

Here is a diagram that hopefully will spell out some high level pieces of this:

代码仅涵盖上图中的1)、2)和5).1) 对 WebView 的调用非常明显.2) 实际上是对 Constants.SINGLE_SIGNON_URL 的调用,它会访问您的服务器,应该重定向到 IDP 页面.当用户在那里登录时,它会被发送回您的服务 (SP) 并重定向回您的 WebView.再一次,我们在 cookie 中存储了一些内容以提取出来以继续我们的正常登录.

The code only covers 1), 2) and 5) in the above diagram. 1) Is pretty obvious the call to the WebView. 2) is really the call to the Constants.SINGLE_SIGNON_URLwhich hits your server, which should redirect to the IDP page. When the user logs in there, it get sent back to your Service (SP) and is redirected back to your WebView. Again, we stored something in the cookie to pull out to continue our normal login.

一个关键是要意识到WebView的shouldOverrideUrlLoading()被多次调用.忽略除发送回服务器 URL 之外的所有其他内容,此时您会提取所需的数据(在我们的示例中是服务器已验证的登录信息).这可以在调用 GlobalState.getInstance().currentUserName = getCookieValue("_username" ,cookies);

One key is to realize that the WebView's shouldOverrideUrlLoading() is called several times. Ignore all of those except the one that sends back your server's URL, at which point you pull out the data you need (in our case the login info that the server had verified). This is seen in the call GlobalState.getInstance().currentUserName = getCookieValue("_username" ,cookies);

可能没有很好地解释这一点(而且已经一个月左右了!).以下是完成大部分工作的 SSOActivity 示例:

Probably not explaining this very well (and it has been a month or so!). Here is a sample of the SSOActivity where most of the work is done:

public class SSOActivity extends Activity {
    WebView webView;
    private Button mCancel;
    private Button mReset;

    /**
     * Grabs the specified variables out of the list of cookies
     * 
     * @param fieldName
     * @param cookies
     * @return
     */
    public String getCookieValue(String fieldName, final String cookies){     
        String CookieValue = null;

        String[] cookiessplit = cookies.split(";");
        for (String str : cookiessplit ) {
            if(str.contains(fieldName)) {
                String[] value=str.split("=");
                CookieValue = value[1];
                break;
            }
        }              
        return CookieValue; 
    }

    public void clearCookies() {
        try {
            android.webkit.CookieManager cookieManager = CookieManager.getInstance();
            cookieManager.removeAllCookie();
        }
        catch (Exception ex) 
        {
            Utilities.logException(ex);
            Utilities.logError("SSOActivity", "clearCookies() : " + ex.getMessage() );
        }
    }

    /**
     * Cancels the SSO request in Webview
     * 
     * @param view
     */
    public void cancelSSOClick (View view) {
        Utilities.logInfo("cancelSSOClick", "Cancel SSO click");
        setResult(Activity.RESULT_CANCELED, null);
        SSOActivity.this.finish();
    }

    /**
     * Resets and deletes cookies and SSOUrl if one exists
     * 
     * @param view
     */
    public void resetSSOClick (View view) {
        Utilities.logInfo("resetSSOClick", "Cancel SSO click");
        setResult(Activity.RESULT_CANCELED, null);
        clearCookies();
        SSOActivity.this.finish();
    }



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setResult(Activity.RESULT_OK, null);

        // Setup the web view. It will redirect to SSO site for login
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_sso);

        mCancel = (Button)findViewById(R.id.cancelSSO);
        mCancel.setTextColor(Color.WHITE);

        mReset = (Button)findViewById(R.id.resetSSO);
        mReset.setTextColor(Color.WHITE);

        webView = (WebView) findViewById(R.id.ssoViewer);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setSupportZoom(false);
        webView.setWebViewClient(new WebViewClient() {
           @Override
            public boolean shouldOverrideUrlLoading (WebView view, String url) {
                try {
                    // If coming from our system, then we need to check the cookie for username password, for
                    // some SSO this might be different than the base url. Check for both
                    if (url.equals(Constants.getBaseUrl()) || url.equals(Constants.SSO_RETURN_URL)) {

                        CookieManager cookieManager = CookieManager.getInstance();
                        final String cookies = cookieManager.getCookie(url);
                        GlobalState.getInstance().currentUserName = getCookieValue("_username" ,cookies);
                        SSOActivity.this.finish();
                        return true;
                    }
                } 
                catch (Exception ex) {
                    GlobalState.getInstance().currentUserName = "";
                    GlobalState.getInstance().currentPassword = "";
                    setResult(Activity.RESULT_CANCELED, null);
                    SSOActivity.this.finish();
                }

                return false;
           }

        });

        try {
            webView.loadUrl(Constants.SINGLE_SIGNON_URL);
        }
        catch (Exception ex) {
            Utilities.logException(ex);
            Utilities.logError("SSOActivity", "onCreate(), webView.loadUrl(ssoUrl) : " + ex.getMessage() );

        }

    }

}

以下是支持活动的 XML 示例:

Here is an example of the XML supporting the Activity:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/ssoViewerLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:id="@+id/button_layout"
                android:layout_width="match_parent"
                android:orientation="horizontal"
                android:layout_height="wrap_content"
                android:gravity="center|bottom"
                android:layout_alignParentBottom="true">      

                <Button
                    android:id="@+id/cancelSSO"
                    android:layout_marginTop="16dp"
                    android:layout_width="125dp"
                    android:layout_height="55dp"
                    android:layout_margin="5dp"
                    android:onClick="cancelSSOClick"
                    android:text="Cancel Login"
                    android:background="@drawable/button_login" />
                <Button
                    android:id="@+id/resetSSO"
                    android:layout_marginTop="16dp"
                    android:layout_width="125dp"
                    android:layout_height="55dp"
                    android:layout_margin="5dp"
                    android:onClick="resetSSOClick"
                    android:text="Reset SSO"
                    android:background="@drawable/button_login"/>
        </LinearLayout>
     <WebView
               android:id="@+id/ssoViewer"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               android:layout_above="@id/button_layout" />  
    </RelativeLayout>

在代码中的其他地方调用它,如下所示:

Calling it else where in the code looks like this:

                        Intent viewIntent = new Intent(getActivity(), SSOActivity.class);
                        (getActivity()).startActivityForResult(viewIntent, Constants.SINGLE_SIGN_ON);

最后你应该看到什么:

希望这会有所帮助!

这篇关于Android SSO Okta 集成示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆