ProjectWise SDK - Bentley IMS Login

I need to use the ProjectWise SDK (not the pwps_dab module) to login using Bentley IMS authentication. The documentation indicates 'aaApi_LoginWithSecurityToken' is the function but I'm not sure how to acquire the 'security token'. Does anyone have a working example they can share? 

Parents
  • I mean to post some code for this, but here's a snippet that may help you, but it is in C#, so you man need to use MostOfDavesClasses.

    You can get that code with the link in this post:  https://communities.bentley.com/products/programming/projectwise_programming/m/mediagallery/273950 

    However that link doesn't demonstrate using IMS authenication.

    So here's the snippet:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    
    namespace SampleIMSConsole
    {
        class Program
        {
            [DllImport("c:\\program files\\bentley\\projectwise\\bin\\dmscli.dll", CharSet = CharSet.Unicode)]
            private static extern bool aaApi_LoginWithSecurityToken(string dataSource, string securityToken, bool asAdmin, string hostname, long[] productIds);
    
            // BOOL aaApi_GetRelyingPartyIdentifier(LPCWSTR pServerName, LPWSTR* ppRelyingPartyIdentifier )
            [DllImport("c:\\program files\\bentley\\projectwise\\bin\\dmscli.dll", CharSet = CharSet.Unicode)]
            private static extern bool aaApi_GetRelyingPartyIdentifier(string serverName, ref string relyingPartyIdentifier);
    
            static void Main(string[] args)
            {
                if (args.Length > 0)
                {
                    string _loginToken = ""; // MyLoginCommands.GetLoginToken(DatasourceName);
    
                    string relyingParty = "";
                    string serverName = args[0].Split(':')[0];
                    bool relyingPartySuccess = aaApi_GetRelyingPartyIdentifier(serverName, ref relyingParty);
    
                    // Contact the Connection Client and ask for the login token.
                    try
                    {
                        Bentley.Connect.Client.API.V1.ConnectClientAPI conn = new Bentley.Connect.Client.API.V1.ConnectClientAPI();
    
                        _loginToken = conn.GetSerializedDelegateSecurityToken(relyingParty);
                    }
                    catch (Exception ex)
                    {
                    }
    
                    if (aaApi_LoginWithSecurityToken(args[0], _loginToken, true, null, null))
                    {
                        Console.WriteLine(string.Format("Logged in OK to '{0}' with BentleyIMS.", args[0]));
                    }
                    else
                    {
                        Console.WriteLine(string.Format("Error logging in to '{0}'", args[0]));
                    }
    
                }
            }
        }
    }
    

    HTHs

  • Thanks Dan, really appreciate the quick reply.

    I've used your approach and can successfully return the secure token but it fails to login. The error detail returned by aaApi_GetLastErrorDetail is 'Invalid user name and password combination.'

    The CONECTION client is signed in and my account is federated on the test datasource. Here's the current code with additional output for testing purposes.

    public static bool LoginBentleyIMS(string dataSource, bool asAdmin, string hostname, bool verbose=false)
            {
                string _loginToken;
    
                string relyingParty = "";
                string serverName = dataSource.Split(':')[0];
    
                if (!dmscli.aaApi_GetRelyingPartyIdentifier(serverName, ref relyingParty))
                {
                    Console.WriteLine(dmsgen.aaApi_GetLastErrorMessage());
                }
    
                // Contact the Connection Client and ask for the login token.
                try
                {
                    Bentley.Connect.Client.API.V1.ConnectClientAPI conn = new Bentley.Connect.Client.API.V1.ConnectClientAPI();
    
                    _loginToken = conn.GetSerializedDelegateSecurityToken(relyingParty);
    
                    if (verbose)
                    {
                        Console.WriteLine(relyingParty);
                        Console.WriteLine(_loginToken);
                    }           
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    return false;
                }
    
                var successfull=dmscli.aaApi_LoginWithSecurityToken(dataSource, _loginToken, asAdmin, hostname, null);
    
                if (successfull)
                {
                    Console.WriteLine(string.Format("Logged in OK to '{0}' with BentleyIMS.", dataSource));
                }
                else
                {
                    Console.WriteLine(dmsgen.aaApi_GetLastErrorMessage());
                    Console.WriteLine(dmsgen.aaApi_GetLastErrorDetail());
                    Console.WriteLine(string.Format("Error logging in to '{0}'", dataSource));
                }
    
                return successfull;
            }

    Added a reference to "C:\Program Files\Common Files\Bentley Shared\CONNECTION Client\Bentley.Connect.Client.API.dll" to access the "Bentley.Connect.Client.API.V1.ConnectClientAPI" class.

    Example call: LoginBentleyIMS("servername:datasource",true,null);

  • Matthew,

    I've got a working sample IMS login that I will be posting soon, but it is a bit different from what I posted for you.  I'm wondering if the fact that you have a federated account that may be the "problem", in that the code I provided to you doesn't account for that situation?  I don't have a federated account to test with, so I'm not sure at this point if that may be the issue.

    If you have time, can you please try using PowerShell (PWPS_DAB) to connect to your datasource using your federated account?  If that works, then I can look at the code behind the Cmdlet (New-PWLogin) and see if there are additional steps being taken to generate a token that works. 

    And if you get the PowerShell login to work, please post or send me an email on the details of how you used it (parameters and values) so that I can explore the path taken through the code behind the Cmdlet as then I should be able to determine what needs to be changed in the sample I provided.

    A private message in communities will work or you can directly email me at Dan.Williams@Bentley.com.

    FWIW, my understanding of how federation works is that the "user" gets a token from their Identify Provider and then that token is passed onto the Federation Provider which generates another token that is passed onto the application (or perhaps the other way around?).  So I wondering if the token you are getting with the sample code I provided is just the one of the steps?

    I'll do my best to try to get this sorted out, but feel free to see if you can generate the "right" token that needs to be passed onto the ProjectWise login function.

    And if you find a way to get a token that works, please post your solution, or at least the approach you took!

Reply
  • Matthew,

    I've got a working sample IMS login that I will be posting soon, but it is a bit different from what I posted for you.  I'm wondering if the fact that you have a federated account that may be the "problem", in that the code I provided to you doesn't account for that situation?  I don't have a federated account to test with, so I'm not sure at this point if that may be the issue.

    If you have time, can you please try using PowerShell (PWPS_DAB) to connect to your datasource using your federated account?  If that works, then I can look at the code behind the Cmdlet (New-PWLogin) and see if there are additional steps being taken to generate a token that works. 

    And if you get the PowerShell login to work, please post or send me an email on the details of how you used it (parameters and values) so that I can explore the path taken through the code behind the Cmdlet as then I should be able to determine what needs to be changed in the sample I provided.

    A private message in communities will work or you can directly email me at Dan.Williams@Bentley.com.

    FWIW, my understanding of how federation works is that the "user" gets a token from their Identify Provider and then that token is passed onto the Federation Provider which generates another token that is passed onto the application (or perhaps the other way around?).  So I wondering if the token you are getting with the sample code I provided is just the one of the steps?

    I'll do my best to try to get this sorted out, but feel free to see if you can generate the "right" token that needs to be passed onto the ProjectWise login function.

    And if you find a way to get a token that works, please post your solution, or at least the approach you took!

Children
  • Matthew,

    "Good news", I can reproduce your problem.

    Using a federated account, I get a valid token with the same code as you did, but when I try to log into my datasource with a federated account, it fails with the same error message as you received.  However, for my test case, the error message was correct.  My target datasource doesn't have an account matching what I used for the CONNECTION Client!  If I use the same CONNECTION Client session for a datasource where that federated account has a matching user account (and enabled, etc.), it works!  

    So, can you please verify that the user credentials you are using for your CONNECTION Client are the same as the federated account in your target datasource?  

  • Hi Dan, again thank you for all your help. Fingers crossed I'll get sometime today to test and get back to you

  • Matthew,

    I updated my post and took out the part about "you might have to login at least once with PW explorer".  I tested this against another datasource where I added the federated user account, but did not log in to that datasource, I just ran my sample application and it logged in just fine.

    However, if your application uses an account that has not logged into ProjectWise Explorer, then unless you manually created that user's working directory on the machine that you are connecting from, any file transfers (check out, copy out, etc.) that need the working directory will fail. FWIW, in my stand alone apps, I check to see if the user has a working directory defined as well as checking to make sure that it exits.  If not, I do that in code.

    Looking forward to hearing if this was your problem or not.

  • Unfortunately its still not working via the API:

    • My working directory exists locally;
    • CONNECTION client is signed in using the same account;
    • Tried switching my account from federated to logical (preserving the federated identity);

    I can login using pwps_dab "New-PWLogin -DatasourceName $DatasourceFullName -BentleyIMS" no issues. I'll keep testing and feedback. Enjoy the weekend.