Login profile

The login profile defines how an individual user logs into Relativity by setting user-specific options for each provider in the authentication profile. Each entry in the user's login profile corresponds to a matching entry in the environment's authentication profile, such as Provider in the environment for Password, Integrated Authentication, Active Directory, RSA, and Client Certificate.

You can interact with the login profile using the ILoginProfileManager interface. The methods on the interface allow you to retrieve and update a user's login profile. You can also send out login invitation emails and manually set passwords.

This page contains the following information:

See these related pages:

Login profile fundamentals

Before programmatically interacting with login profiles, familiarize yourself with the Relativity authentication provider user interface and review the information in the Relativity Documentation site. Note there is a strong correlation between the API operations and object properties and the user interface elements.

Use these guidelines when working with authentication methods:

  • To access the ILoginManager interface, add the Relativity.Services.Interfaces.dll reference to your Visual Studio project. The file can be found in the Relativity SDK. For more information, see Set up your development environment.
  • The user must have the permissions required for working with Relativity login methods.
  • Login methods are interacted with through the user login method profile. The profile is the collection of all the methods for that user.
  • There can only be one method instance for each authentication provider.
  • A user can only have one of the following provider type methods active at any one time: Password, RSA, Active Directory.

Get the login profile

To read a user's profile, call the GetLoginProfileAsync method of the ILoginProfileManager interface with the user's Artifact ID:

Relativity.Services.Security.Models.LoginProfile userProfile = await loginProfileManager.GetLoginProfileAsync (13775096);

Update the login profile

To set the login profile for a user:

  1. First call the GetLoginProfileAsync method of the ILoginProfileManager interface with the user's Artifact ID:
    Relativity.Services.Security.Models.LoginProfile userProfile = await loginProfileManager.GetLoginProfileAsync (13775096);	
  2. Then make any updates required to the profile.
    //Password
    userProfile.Password = New Relativity.Services.Security.Models.PasswordMethod()
    {
        //Required
        IsEnabled = true,
        MustResetPasswordOnNextLogin = false,
        PasswordExpirationInDays = 30,
        UserCanChangePassword = true,
        TwoFactorMode = Relativity.Services.Security.Models.TwoFactorMode.Always,
        //Required for Two Factor Always And Outside Ips
        TwoFactorInfo = "1115551212@mobileprovider.example.com"
    };
    
    //Active Directory
    userProfile.ActiveDirectory = New Relativity.Services.Security.Models.ActiveDirectoryMethod()
    {
        IsEnabled = true,
        Account = "myAccount@testing"
    };
  3. Finally call the SaveLoginProfileAsync method of the ILoginProfileManager interface to complete the update.
    await loginProfileManager.SaveLoginProfileAsync (userProfile );	

Send login invitation email 

After you enable a password authentication provider for a user, for example, password-only or password two-factor, you must send an invitation email for the user to log in to Relativity and change their password.

Note: The user sending the invitations must have edit permissions to the users who are being invited.

The following instance settings define the parameters of the invitation workflow:

  • InvitationEmailRequestBody (Relativity.Authentication section) - the invitation email message text. The email text must be formatted as HTML.
  • InvitationEmailRequestFrom (Relativity.Authentication section) – the invitation email message sender's email address.
  • InvitationEmailRequestSubject (Relativity.Authentication section) – the invitation email message subject.
  • InvitationLinkLifetimeInMin (Relativity.Authentication section) – the number of minutes the link sent in the invitation email remains valid.

For more information about instance settings, see the Relativity Documentation site.

The Relativity URL in the invitation email can be defined by the following in the order of precedence:

  • Site URL property on the authentication profile – if you have an OIDC or SAML2 provider, otherwise the property is not present.
  • PasswordNotificationRelativityURL (kCura.Relativity section) instance setting.
  • RelativityInstanceURL (Relativity.Core section) instance setting.

Before sending invitation emails, you can test whether the users can be invited with the VerifyBulkInvitationAsync method. You must pass the method a list of Artifact IDs of users.

BulkInvitationResponse verifyResponse = client.VerifyBulkInvitationAsync(new List<int> { 9, -1, 1016613, 1016820 }).Result;
if (!verifyResponse.Success)
{
   // verifyResponse.Success == true iff verifyResponse.Errors.Any() == true
   foreach (UserInviteError error in verifyResponse.Errors)
   {
      Console.WriteLine("VERIFY: Error occurred for user {0}: {1} ({2})", error.UserId, error.Exception.Message, (int)error.StatusCode);
   }
}

The following condition are tested:

  • Whether the user(s) have a login method enabled.
  • Whether the SMTP server is configured.
  • Whether the Relativity instance URL is configured.

The returned BulkInvitationResponse object contains any validation errors.

To send the invitation email to a single user, call the SendInvitationAsync method of the ILoginProfileManager interface passing it the Artifact ID of the user:

await loginProfileManager.SendInvitationAsync(13775096);

Executing the operation results in an email sent to the user's address:

Sample email sent to userby calling the SendInvitationAsync() method

You can send invitations to multiple users with the SendBulkInvitationAsync method:

BulkInvitationResponse sendResponse = client.SendBulkInvitationAsync(new List<int> { 9, -1, 1016613, 1016820 }).Result;
if (!sendResponse.Success)
{
   // verifyResponse.Success == true if verifyResponse.Errors.Any() == false
   foreach (UserInviteError error in sendResponse.Errors)
   {
      Console.WriteLine("SEND: Error occurred for user {0}: {1} ({2})", error.UserId, error.Exception.Message, (int)error.StatusCode);
   }
}

Set user's password

By default, system admins can't set user passwords. Instead, system admins can send a password reset email, and users create and manage their own passwords. However, there are some situations, such as for testing or project development, that may require system admins to explicitly and manually set passwords.

To set this option in your Relativity instance, add the AdminsCanSetPasswords instance setting in the Relativity.Authentication section and set it to True. For more information, see Instance settings.

For more information about instance settings, see the Relativity Documentation site.

To set the password, call the SetPasswordAsync method of the ILoginProfileManager interface passing it the Artifact ID of the user and the password string:

await loginProfileManager.SetPasswordAsync(13775096, "PowerPC1991!");

Login Profile Manager REST service

The Login Profile Manager service allows you to interact with authentication provider from browser-based and cross-platform applications. The service provides the same set of operations as the ILoginProfileManager .NET interface - get and update the login profile, send invitation email, and reset password.

Get a user's login profile with REST

To get a user's login method profile, send a POST request to the following Login Profile Manager service URL:

/Relativity.Rest/api/Relativity.Services.Security.ISecurityModule/Login Profile Manager/GetLoginProfileAsync

The request payload must include the user's ArtifactID.

{
  "userId": 13775096  
} 

Sample JSON response:

	
{
  "profile": {
    "UserId": 13775096,
    "Password": {
      "InvalidLoginAttempts": 1,
      "IsEnabled": true,
      "MustResetPasswordOnNextLogin": false,
      "UserCanChangePassword": true,
      "PasswordExpirationInDays": 30,
      "PasswordExpires": "2016-07-28T19:03:59.93",
      "TwoFactorMode": "None"
    },
    "IntegratedAuthentication": {
      "Account": "testing\\windowsAccount",
      "IsEnabled": true
    },
    "ActiveDirectory": {
      "Account": "myAccount@testing",
      "IsEnabled": false
    },
    "ClientCertificate": {
      "Subject": "testinguser@gmail.com",
      "IsEnabled": true
    },
    "RSA": {
      "Subject": "rsaUserAccount",
      "IsEnabled": false
    },
    "OpenIdConnectMethods": [
      {
        "ProviderName": "Azure Active Directory Provider",
        "Subject": "BE02DE11-5D90-4ADF-9D8F-164806AEA03C",
        "IsEnabled": true
      }
    ],
    "SAML2Methods": [
      {
        "ProviderName": "Okta",
        "Subject": "someUser@domain.com",
        "IsEnabled": true
      }
    ]
  }
}			

Update a user's profile with REST

To update a users profile, send a POST request to the following Auth Manager service URL:

/Relativity.REST/api/Relativity.Services.Security.ISecurityModule/Login Profile Manager/SaveLoginProfileAsync

The following is a sample request for updating a user's profile with a method of each provider type:

{
  "profile": {
    "UserId": 13775096,
    "Password": {
      "InvalidLoginAttempts": 1,
      "IsEnabled": true,
      "MustResetPasswordOnNextLogin": false,
      "UserCanChangePassword": true,
      "PasswordExpirationInDays": 30,
      "PasswordExpires": "2016-07-28T19:03:59.93",
      "TwoFactorMode": "None"
    },
    "IntegratedAuthentication": {
      "Account": "testing\\windowsAccount",
      "IsEnabled": true
    },
    "ActiveDirectory": {
      "Account": "myAccount@testing",
      "IsEnabled": false
    },
    "ClientCertificate": {
      "Subject": "testinguser@gmail.com",
      "IsEnabled": true
    },
    "RSA": {
      "Subject": "rsaUserAccount",
      "IsEnabled": false
    },
    "OpenIdConnectMethods": [
      {
        "ProviderName": "Azure Active Directory Provider",
        "Subject": "BE02DE11-5D90-4ADF-9D8F-164806AEA03C",
        "IsEnabled": true
      }
    ],
    "SAML2Methods": [
      {
        "ProviderName": "Okta",
        "Subject": "someUser@domain.com",
        "IsEnabled": true
      }
    ]
  }
}		

Send invitation email with REST

Before sending invitation emails, you can test whether the users can be invited. Issue a POST request to the following Login Profile Manager service URL:

/Relativity.Rest/api/Relativity.Services.Security.ISecurityModule/Login Profile Manager/SendInvitationAsync

The request payload must include the list of user ArtifactIDs.

{
  "userIdList": [
    1024900,
    121244141,
    1023800
  ]
}

The response contains any validation errors:

{
  "Success": false,
  "Errors": [
    {
      "UserId": 1024900,
      "Exception": {
        "ClassName": "System.InvalidOperationException",
        "Message": "No usable login method available",
        "Data": null,
        "InnerException": null,
        "HelpURL": null,
        "StackTraceString": "   at Relativity.Core.Api.Security.Service.LoginProfileService.<>c__DisplayClass28_0.<<SendInvitationInnerAsync>b__0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Shared.Data.CoreBaseContext.IDataSessionExtensions.<DoWorkInTran>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendInvitationInnerAsync>d__28.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendBulkInvitationAsync>d__31.MoveNext()",
        "RemoteStackTraceString": null,
        "RemoteStackIndex": 0,
        "ExceptionMethod": "8\nMoveNext\nRelativity.Core.Api, Version=9.4.0.0, Culture=neutral, PublicKeyToken=null\nRelativity.Core.Api.Security.Service.LoginProfileService+<>c__DisplayClass28_0+<<SendInvitationInnerAsync>b__0>d\nVoid MoveNext()",
        "HResult": -2146233079,
        "Source": "Relativity.Core.Api",
        "WatsonBuckets": null
      },
      "StatusCode": "InternalServerError"
    },
    {
      "UserId": 121244141,
      "Exception": {
        "ClassName": "Relativity.Core.Api.Shared.Exceptions.EntityNotFoundException",
        "Message": null,
        "Data": null,
        "InnerException": null,
        "HelpURL": null,
        "StackTraceString": "   at Relativity.Core.Api.Security.DataAccess.LoginProfileRepository.<ReadAsync>d__12.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<>c__DisplayClass28_0.<<SendInvitationInnerAsync>b__0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Shared.Data.CoreBaseContext.IDataSessionExtensions.<DoWorkInTran>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendInvitationInnerAsync>d__28.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendBulkInvitationAsync>d__31.MoveNext()",
        "RemoteStackTraceString": null,
        "RemoteStackIndex": 0,
        "ExceptionMethod": "8\nMoveNext\nRelativity.Core.Api, Version=9.4.0.0, Culture=neutral, PublicKeyToken=null\nRelativity.Core.Api.Security.DataAccess.LoginProfileRepository+<ReadAsync>d__12\nVoid MoveNext()",
        "HResult": -2146233088,
        "Source": "Relativity.Core.Api",
        "WatsonBuckets": null
      },
      "StatusCode": "InternalServerError"
    },
    {
      "UserId": 1023800,
      "Exception": {
        "ClassName": "Relativity.Core.Api.Security.Domain.Exceptions.InvalidPasswordOperationException",
        "Message": "The RelativityInstanceURL EDDS configuration setting is not set",
        "Data": null,
        "InnerException": null,
        "HelpURL": null,
        "StackTraceString": "   at Relativity.Core.Api.Security.PasswordLogic.InvitationUriBuilder.GetBaseUri(AuthProfile authProfile)\r\n   at Relativity.Core.Api.Security.PasswordLogic.InvitationUriBuilder.BuildInvitationUri(AuthProfile authProfile, PasswordResetToken token)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<>c__DisplayClass28_0.<<SendInvitationInnerAsync>b__0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Shared.Data.CoreBaseContext.IDataSessionExtensions.<DoWorkInTran>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendInvitationInnerAsync>d__28.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendBulkInvitationAsync>d__31.MoveNext()",
        "RemoteStackTraceString": null,
        "RemoteStackIndex": 0,
        "ExceptionMethod": "8\nGetBaseUri\nRelativity.Core.Api, Version=9.4.0.0, Culture=neutral, PublicKeyToken=null\nRelativity.Core.Api.Security.PasswordLogic.InvitationUriBuilder\nSystem.Uri GetBaseUri(Relativity.Core.Api.Security.Domain.AuthProfile)",
        "HResult": -2146233088,
        "Source": "Relativity.Core.Api",
        "WatsonBuckets": null
      },
      "StatusCode": "InternalServerError"
    }
  ]
}

To send an invitation email, issue a POST request to the following Login Profile Manager service URL:

/Relativity.Rest/api/Relativity.Services.Security.ISecurityModule/Login Profile Manager/SendInvitationAsync

The request payload must include the user's ArtifactID.

{
  "userId": 13775096
} 

To send invitations to multiple users, issue a POST request to the following Login Profile Manager service URL:

/Relativity.Rest/api/Relativity.Services.Security.ISecurityModule/Login Profile Manager/SendBulkInvitationAsync

The request payload must include the list of user ArtifactIDs.

{
  "userIdList": [
    1024900,
    121244141,
    1023800
  ]
}

If any of the invitations fail to be sent, the response returns the Success flag with the value of false, and the errors for specific users:

{
  "Success": false,
  "Errors": [
    {
      "UserId": 1024900,
      "Exception": {
        "ClassName": "System.InvalidOperationException",
        "Message": "No usable login method available",
        "Data": null,
        "InnerException": null,
        "HelpURL": null,
        "StackTraceString": "   at Relativity.Core.Api.Security.Service.LoginProfileService.ValidateInvitationShouldBeSent(IDataSession session, LoginProfile loginProfile)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<>c__DisplayClass29_0.<<SendInvitationInnerAsync>b__0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Shared.Data.CoreBaseContext.IDataSessionExtensions.<DoWorkInTran>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendInvitationInnerAsync>d__29.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendBulkInvitationAsync>d__32.MoveNext()",
        "RemoteStackTraceString": null,
        "RemoteStackIndex": 0,
        "ExceptionMethod": "8\nValidateInvitationShouldBeSent\nRelativity.Core.Api, Version=9.4.0.0, Culture=neutral, PublicKeyToken=null\nRelativity.Core.Api.Security.Service.LoginProfileService\nVoid ValidateInvitationShouldBeSent(Relativity.Core.Api.Shared.Data.IDataSession, Relativity.Core.Api.Security.Domain.LoginMethods.LoginProfile)",
        "HResult": -2146233079,
        "Source": "Relativity.Core.Api",
        "WatsonBuckets": null
      },
      "StatusCode": 422
    },
    {
      "UserId": 1023800,
      "Exception": {
        "ClassName": "System.InvalidOperationException",
        "Message": "No usable login method available",
        "Data": null,
        "InnerException": null,
        "HelpURL": null,
        "StackTraceString": "   at Relativity.Core.Api.Security.Service.LoginProfileService.ValidateInvitationShouldBeSent(IDataSession session, LoginProfile loginProfile)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<>c__DisplayClass29_0.<<SendInvitationInnerAsync>b__0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Shared.Data.CoreBaseContext.IDataSessionExtensions.<DoWorkInTran>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendInvitationInnerAsync>d__29.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Relativity.Core.Api.Security.Service.LoginProfileService.<SendBulkInvitationAsync>d__32.MoveNext()",
        "RemoteStackTraceString": null,
        "RemoteStackIndex": 0,
        "ExceptionMethod": "8\nValidateInvitationShouldBeSent\nRelativity.Core.Api, Version=9.4.0.0, Culture=neutral, PublicKeyToken=null\nRelativity.Core.Api.Security.Service.LoginProfileService\nVoid ValidateInvitationShouldBeSent(Relativity.Core.Api.Shared.Data.IDataSession, Relativity.Core.Api.Security.Domain.LoginMethods.LoginProfile)",
        "HResult": -2146233079,
        "Source": "Relativity.Core.Api",
        "WatsonBuckets": null
      },
      "StatusCode": 422
    }
  ]

If all invitations are successfully sent, the response does not contain any errors:

{
  "Success": true,
  "Errors": []
}

Set users password with REST

To set the user's password, send a POST request to the following Login Profile Manager service URL:

/Relativity.Rest/api/Relativity.Services.Security.ISecurityModule/Login Profile Manager/SetPasswordAsync

The request payload must include the user's ArtifactID and the password string value:

{
  "userId": 13775096,
  "password": "PowerPC1991!"   
} 

Additional Resources

DevHelp Community GitHub Release Notes NuGet

Share knowledge with the Relativity developer community.

Access tools and resources to build an application.

Review the most recent product release notes.

Create .NET Apps faster with NuGet.