SFAuthenticationSession Launching "Blank"

RyanMendozaRyanMendoza USMember ✭✭
edited April 2018 in General

Hi all,

I am having an issue when trying to use the SFAuthenticationSession class to log a user in. I had this previously working (prompting for permission, loading my OIDC login page, going back to app after successful login with results), but it seems as I've gone down the road with my project it is now launching blank.

Note: I tried adding an image but I got a message saying I'm too new to the forums to do so.

My initial gut feeling is that this has something to do with Linking. I do have a LinkDescription.xml file with build type of LinkDescription:

<?xml version="1.0" encoding="utf-8" ?>
<linker>
    <assembly fullname="EmployeeApp">
        <type fullname="*"></type>
    </assembly>
    <assembly fullname="EmployeeApp.iOS">
        <type fullname="*"></type>
    </assembly>
    <assembly fullname="IdentityModel">
        <type fullname="*"></type>
    </assembly>
    <assembly fullname="IdentityModel.OidcClient">
        <type fullname="*"></type>
    </assembly>
        <assembly fullname="Microsoft.IdentityModel.Tokens">
        <type fullname="*"></type>
    </assembly>
    <assembly fullname="Newtonsoft.Json">
        <type fullname="*"></type>
    </assembly>
    <assembly fullname="System.IdentityModel.Tokens.Jwt">
        <type fullname="*"></type>
    </assembly>
</linker>

Here is my SFAuthenticationSession implementation (inside the EmployeeApp.iOS project):

using Foundation;
using System.Threading.Tasks;
using IdentityModel.OidcClient.Browser;
using SafariServices;

namespace EmployeeApp.iOS
{
    public class SFAuthenticationSessionBrowser : IBrowser
    {
        SFAuthenticationSession _sf;

        public Task<BrowserResult> InvokeAsync(BrowserOptions options)
        {
            var wait = new TaskCompletionSource<BrowserResult>();

            _sf = new SFAuthenticationSession(new NSUrl(options.StartUrl), options.EndUrl,
                (callbackUrl, error) =>
                {
                    if (error != null)
                    {
                        var errorResult = new BrowserResult
                        {
                            ResultType = BrowserResultType.UserCancel,
                            Error = error.ToString()
                        };

                        wait.SetResult(errorResult);
                    }
                    else
                    {
                        var result = new BrowserResult
                        {
                            ResultType = BrowserResultType.Success,
                            Response = callbackUrl.AbsoluteString
                        };

                        wait.SetResult(result);
                    }
                });

            _sf.Start();

            return wait.Task;
        }
    }
}

And here is where I kick all of this off from a LoginPage in my shared Xamarin.Forms project (.NET Standard 2.0):

        public LoginPage(bool doLogin = true)
        {
            InitializeComponent();

            var browser = DependencyService.Get<IBrowser>();

            var options = new OidcClientOptions
            {
                Authority = "<redacted>",
                ClientId = "employeeapp",
                Scope = "openid profile email api offline_access",
                RedirectUri = "employeeapp://callback",
                Browser = browser,

                ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect
            };

            _client = new OidcClient(options);

            if (doLogin) DoLogin();
        }

        async void DoLogin()
        {
            _result = await _client.LoginAsync(new LoginRequest());

            if (_result.IsError)
            {
                OutputText.Text = _result.Error;

                return;
            }

            SaveCredentials(
                _result.User.Claims.SingleOrDefault(cw => cw.Subject.Equals("username")).Value, 
                _result.AccessToken, _result.RefreshToken, 
                _result.AccessTokenExpiration.ToString()
            );

            Application.Current.MainPage = new MainPage();
        }

Note: I tried posting this to Xamarin.Forms, not General.

Answers

  • gayanpereragayanperera USMember ✭✭

    Hi @RyanMendoza,

    I have a concern about SFAuthenticationSession, when i had logged successfully with external server and then, I close the app without logout in the second time it's asking to enter the username and password itself.

    I'm confusing with without logout why app required login credentials. Seem my logged SFAuthenticationSession has not stored my previous logged session, Do you have any solution or experience how to overcome this thing?

    Thanks -

Sign In or Register to comment.