Movement Services | ARAMS - Authentication
ARAMS (Animal Reporting and Movement Service) provides secure authentication for recording livestock movements in England. This document covers authentication requirements, implementation details, and best practices for both Farm and Abattoir service variants.
Table of Contents
- Overview
- Authentication Flow
- Prerequisites
- Credential Types
- Setup
- Farm Service Authentication
- Abattoir Service Authentication
- Security Implementation
- Credential Validation
- Error Handling
- Test Environment
Overview
ARAMS authentication uses a three-tier credential system:
- Service Provider Credentials - Identify your software/service provider to ARAMS
- Property Credentials - User credentials for the specific farm or abattoir property
- SOAP Security Headers - WS-Security username/password tokens in SOAP requests
The authentication process validates all three levels before processing any livestock movement transactions. This multi-layer approach ensures that only authorized service providers and users can record movements on behalf of properties.
Authentication Flow
┌─────────────────────────────────────────────────────────┐
│ Client Application │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Prepares Transaction with Credentials: │ │
│ │ - Service Provider ID & Password │ │
│ │ - Property Username & Password │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
↓
┌───────────────────────────────┐
│ EasiTrace API Gateway │
│ │
│ 1. Validates all credentials │
│ 2. Creates SOAP request │
│ 3. Builds WS-Security header │
└───────────────────────────────┘
│
↓
┌───────────────────────────────┐
│ ARAMS Web Service │
│ │
│ 1. Validates credentials │
│ 2. Processes movement │
│ 3. Returns response │
└───────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────┐
│ Response Handling │
│ ┌──────────────────────────────────────────────────┐ │
│ │ - Success: Movement recorded │ │
│ │ - Auth Failure: Invalid credentials │ │
│ │ - Validation Error: Movement validation failed │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Prerequisites
To use ARAMS authentication, you must have:
- Service Provider Registration with ARAMS
- Contact ARAMS to register as an approved software supplier
- Receive a Service Provider ID (username) and Service Provider Password
- These credentials identify your software solution to ARAMS
- Farm or Abattoir Property Access
- Property users need valid ARAMS credentials for their property
- These are the same credentials used to log into ARAMS directly
- Each property has separate username/password credentials
- Property Location Code (CPH)
- Common Purpose Holding identifier for the farm or abattoir
- Format: XX/XXX/XXXX (e.g., “08/050/0046”)
- Required for all transaction submissions
- Network Configuration
- HTTPS access to ARAMS web services
- TLS 1.2 or higher support
- Outbound connections to:
- Test:
https://testws.arams.co.uk/FarmServices/services/ - Production:
https://webservices.arams.co.uk/FarmServices/services/
- Test:
Credential Types
Service Provider Authentication
Identifies the software supplier making requests to ARAMS:
public class ServiceProviderAuthentication
{
public string Username { get; set; } // Service Provider ID from ARAMS
public string Password { get; set; } // Service Provider Password (SoftwareSupplierID)
public string ProgramName { get; set; } // Your application name
public string ProgramVersion { get; set; } // Your application version
public string SchemaVersion { get; set; } // ARAMS schema version
}
Usage in Farm Service:
Username= Software Supplier ID (transmitted in SOAP request)Password= Software Supplier ID (used for WSSE security header)
Usage in Abattoir Service:
Username= Software Supplier ID (used in AbattoirMovements.SoftwareSupplierID)Password= Not used in standard abattoir operations
Property Authentication
Credentials for the specific farm or abattoir user:
public class PropertyAuthentication
{
public string PropertyType { get; set; } // "F" for Farm, "A" for Abattoir
public string Username { get; set; } // ARAMS user login for the property
public string Password { get; set; } // ARAMS user password
}
These are the same credentials the property owner/manager uses to access ARAMS directly.
Setup
Step 1: Store Credentials Securely
Never store credentials in source code. Use environment variables or secure vaults:
// Configuration example using environment variables
var serviceProviderId = Environment.GetEnvironmentVariable("ARAMS_SP_USERNAME");
var serviceProviderPassword = Environment.GetEnvironmentVariable("ARAMS_SP_PASSWORD");
var propertyUsername = Environment.GetEnvironmentVariable("ARAMS_PROPERTY_USERNAME");
var propertyPassword = Environment.GetEnvironmentVariable("ARAMS_PROPERTY_PASSWORD");
Step 2: Prepare Authentication Object
var authentication = new Authentication
{
ServiceProviderAuth = new ServiceProviderAuthentication
{
Username = "ABC123456", // Service Provider ID from ARAMS
Password = "ABC123456", // Service Provider Password
ProgramName = "YourApplication",
ProgramVersion = "1.0.0",
SchemaVersion = "2.0"
},
PropertyAuth = new PropertyAuthentication
{
PropertyType = "F", // "F" for Farm, "A" for Abattoir
Username = "farm_user@arams.co.uk", // ARAMS property user login
Password = "secure_password_here" // ARAMS property user password
}
};
Step 3: Create Transaction with Authentication
{
"reference": "MOVEMENT-2024-001",
"transactionDate": "2024-01-15T10:30:00+00:00",
"type": "MOV-ON",
"speciesCode": "S",
"propertyIdentifier": "08/050/0046",
"authentication": {
"serviceProviderAuth": {
"username": "ABC123456",
"password": "ABC123456",
"programName": "YourApplication",
"programVersion": "1.0.0",
"schemaVersion": "2.0"
},
"propertyAuth": {
"propertyType": "F",
"username": "farm_user@arams.co.uk",
"password": "secure_password_here"
}
},
"fields": {
"ARAMS.Farm.Sheep.Departure.Location": "08/050/0046",
"ARAMS.Farm.Sheep.Departure.Date": "2024-01-15",
"ARAMS.Farm.Sheep.Destination.Location": "35/121/0016",
"ARAMS.Farm.Sheep.Movement.Arrival.Date": "2024-01-15"
},
"animals": [
{
"rfid": "826590066101017",
"visual": "UK12345"
}
]
}
Farm Service Authentication
Required Credentials for Farm Operations
The ARAMS Farm service requires all three credential levels:
// Farm service credential requirements
public override RequiredCredentials RequiredCredentials =>
RequiredCredentials.ServiceProviderPassword
| RequiredCredentials.PropertyUsername
| RequiredCredentials.PropertyPassword;
Credential Validation for Farms
ARAMS Farm validates credentials by attempting a test notification transaction:
public class UserCredentialValidator : IUserCredentialValidator<AramsMovementService>
{
public bool Validate(string username, ref string password,
ServiceProviderAuthentication serviceProviderAuth)
{
// Create test authentication
var auth = new Authentication()
{
ServiceProviderAuth = serviceProviderAuth,
PropertyAuth = new PropertyAuthentication()
{
PropertyType = "F",
Username = username,
Password = password
}
};
// Create minimal test transaction
var transaction = new Transaction()
{
PropertyIdentifier = "00/000/0000",
SpeciesCode = Species.Sheep.Value,
HeadCount = 0,
TransactionDate = DateTime.Now
};
// Pack transaction with provided credentials
var packed = _container.Packer.Pack(transaction, auth);
// Send test request to validate credentials
var response = _container.Sender.Send(
ServiceCapability.NotifyIncomingMovements,
packed,
auth);
// Validate response indicates successful authentication
if (!response.Success || string.IsNullOrWhiteSpace(response.RawResult))
return false;
var parsed = _container.Parser.Process(response.RawResult, transaction);
return parsed.Status == ResponseResultStatus.Success;
}
}
Farm Service Supported Operations
| Transaction Type | Property Credentials Required | Service Provider Credentials Required |
|---|---|---|
| MOV-OFF | Yes | Yes |
| UPDATEMOV-OFF | Yes | Yes |
| MOV-ON | Yes | Yes |
| UPDATEMOV-ON | Yes | Yes |
| MOV-IN | Yes | Yes |
Example: Farm Movement Transaction
{
"reference": "FARM-MOV-OFF-20240115",
"transactionDate": "2024-01-15T10:30:00+00:00",
"type": "MOV-OFF",
"speciesCode": "S",
"propertyIdentifier": "08/050/0046",
"authentication": {
"serviceProviderAuth": {
"username": "ABC123456",
"password": "ABC123456"
},
"propertyAuth": {
"propertyType": "F",
"username": "john.smith@farm.co.uk",
"password": "farm_secure_pwd"
}
},
"fields": {
"ARAMS.Farm.Sheep.Movement.WithinYourBusiness": "Y",
"ARAMS.Farm.Sheep.Departure.Location": "08/050/0046",
"ARAMS.Farm.Sheep.Departure.PostCode": "TF6 6JT",
"ARAMS.Farm.Sheep.Departure.Date": "2024-01-15",
"ARAMS.Farm.Sheep.Movement.LoadingDate": "2024-01-15",
"ARAMS.Farm.Sheep.Movement.ExpectedDuration": "2",
"ARAMS.Farm.Sheep.Destination.Location": "35/121/0016",
"ARAMS.Farm.Sheep.Destination.PostCode": "SY21 8HZ",
"ARAMS.Farm.Sheep.Movement.Haulier.Type": "Haulier",
"ARAMS.Farm.Sheep.Movement.Haulier.VehicleRegistration": "AB21 XYZ",
"ARAMS.Farm.Sheep.Movement.Haulier.AuthorisationNumber": "1234567",
"ARAMS.Farm.Sheep.Movement.Haulier.Name": "John Smith",
"ARAMS.Farm.Sheep.Movement.Haulier.PhoneNumber": "01234567890",
"ARAMS.Farm.Sheep.Movement.Haulier.HaulageCompany": "Swift Transport Ltd"
},
"animals": [
{
"rfid": "826590066101017",
"visual": "UK12345",
"birthDate": "2021-03-15"
},
{
"rfid": "826590066101018",
"visual": "UK12346",
"birthDate": "2021-03-16"
}
]
}
Abattoir Service Authentication
Required Credentials for Abattoir Operations
The ARAMS Abattoir service requires the same three credential levels:
// Abattoir service credential requirements
public override RequiredCredentials RequiredCredentials =>
RequiredCredentials.ServiceProviderPassword
| RequiredCredentials.PropertyUsername
| RequiredCredentials.PropertyPassword;
Credential Validation for Abattoirs
Abattoir validation uses the same test transaction approach:
public class UserCredentialValidator : IUserCredentialValidator<AramsAbattoirMovementService>
{
public bool Validate(string username, ref string password,
ServiceProviderAuthentication serviceProviderAuth)
{
var auth = new Authentication()
{
ServiceProviderAuth = serviceProviderAuth,
PropertyAuth = new PropertyAuthentication()
{
PropertyType = "F",
Username = username,
Password = password
}
};
var transaction = new Transaction()
{
PropertyIdentifier = "00/000/0000",
SpeciesCode = Species.Sheep.Value,
HeadCount = 0,
TransactionDate = DateTime.Now,
Type = ServiceCapability.NotifyIncomingMovements.Code
};
var packed = _container.Packer.Pack(transaction, auth);
var response = _container.Sender.Send(
ServiceCapability.NotifyIncomingMovements,
packed,
auth);
if (!response.Success || string.IsNullOrWhiteSpace(response.RawResult))
return false;
var parsed = _container.Parser.Process(response.RawResult, transaction);
return parsed.Status == ResponseResultStatus.Success;
}
}
Abattoir Service Supported Operations
| Transaction Type | Property Credentials Required | Service Provider Credentials Required |
|---|---|---|
| MOV-ON | Yes | Yes |
| UPDATEMOV-ON | Yes | Yes |
| MOV-CANCEL | Yes | Yes |
| MOV-IN | Yes | Yes |
Example: Abattoir Movement Transaction
{
"reference": "ABATTOIR-MOV-ON-20240115",
"transactionDate": "2024-01-15T14:00:00+00:00",
"type": "MOV-ON",
"speciesCode": "S",
"propertyIdentifier": "40/XXX/0001",
"authentication": {
"serviceProviderAuth": {
"username": "ABC123456",
"password": "ABC123456"
},
"propertyAuth": {
"propertyType": "A",
"username": "slaughterhouse_user",
"password": "abattoir_secure_pwd"
}
},
"fields": {
"ARAMS.Abattoir.Sheep.Destination.Location": "40/XXX/0001",
"ARAMS.Abattoir.Sheep.Movement.Arrival.Date": "2024-01-15",
"ARAMS.Abattoir.Sheep.Movement.Arrival.UnloadingDate": "2024-01-15",
"ARAMS.Abattoir.Sheep.Movement.Haulier.Type": "Haulier",
"ARAMS.Abattoir.Sheep.Movement.Haulier.VehicleRegistration": "AB21 XYZ",
"ARAMS.Abattoir.Sheep.Movement.Haulier.AuthorisationNumber": "7654321",
"ARAMS.Abattoir.Sheep.Movement.Haulier.Name": "Driver Name",
"ARAMS.Abattoir.Sheep.Movement.SatisfiesFCI": true
},
"animals": [
{
"rfid": "826590066101017",
"visual": "UK12345"
}
]
}
Key Differences: Abattoir vs Farm
Service Provider Credential Usage:
- Farm: Username used in SOAP request, Password used in WSSE header
- Abattoir: Username used in AbattoirMovements.SoftwareSupplierID field
Property Type:
- Farm: PropertyType = “F”
- Abattoir: PropertyType = “A”
Supported Operations:
- Farm: Includes MOV-OFF (movement off farm) operations
- Abattoir: Includes MOV-CANCEL (cancel incoming movement) operations
Security Implementation
SOAP WS-Security Headers
ARAMS uses WS-Security (WSSE) with username and password tokens:
// SecurityHeader implementation
internal class SecurityHeader : System.ServiceModel.Channels.MessageHeader
{
public string userName;
public string password;
protected override void OnWriteStartHeader(
System.Xml.XmlDictionaryWriter writer,
System.ServiceModel.Channels.MessageVersion messageVersion)
{
writer.WriteStartElement("wsse", Name, WsseNamespace);
writer.WriteXmlnsAttribute("wsse", WsseNamespace);
writer.WriteXmlnsAttribute("wsu", WsuNamespace);
writer.WriteAttributeString("s", "mustUnderstand", Namespace, "1");
}
protected override void OnWriteHeaderContents(
System.Xml.XmlDictionaryWriter writer,
System.ServiceModel.Channels.MessageVersion messageVersion)
{
DateTime createdTimestamp = DateTime.Now;
DateTime expiresTimestamp = createdTimestamp.AddMinutes(5);
// Write timestamp (5-minute validity window)
writer.WriteStartElement("wsu", "Timestamp", WsuNamespace);
writer.WriteAttributeString("wsu", "Id", WsuNamespace, "TS-48");
writer.WriteStartElement("wsu", "Created", WsuNamespace);
writer.WriteValue(createdTimestamp);
writer.WriteEndElement();
writer.WriteStartElement("wsu", "Expires", WsuNamespace);
writer.WriteValue(expiresTimestamp);
writer.WriteEndElement();
writer.WriteEndElement();
// Write username token
writer.WriteStartElement("wsse", "UsernameToken", WsseNamespace);
writer.WriteAttributeString("wsu", "Id", WsuNamespace, "UsernameToken-47");
writer.WriteStartElement("wsse", "Username", WsseNamespace);
writer.WriteValue(userName); // Property username
writer.WriteEndElement();
writer.WriteStartElement("wsse", "Password", WsseNamespace);
writer.WriteAttributeString("Type",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
writer.WriteValue(password); // Property password
writer.WriteEndElement();
writer.WriteEndElement();
}
public override string Name => "Security";
public string WsseNamespace =>
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
public string WsuNamespace =>
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
public override string Namespace =>
"http://www.w3.org/2003/05/soap-envelope";
}
HTTPS Requirement
All communication with ARAMS endpoints must use HTTPS with:
- TLS 1.2 or higher
- Valid certificate verification
- Secure transport enabled on WCF binding:
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
{
MaxBufferPoolSize = 2147483647,
MaxReceivedMessageSize = 2147483647
};
Credential Storage Best Practices
- Never hardcode credentials in source code
- Use environment variables for local development:
export ARAMS_SP_USERNAME=ABC123456 export ARAMS_SP_PASSWORD=ABC123456 export ARAMS_PROPERTY_USERNAME=user@farm.co.uk export ARAMS_PROPERTY_PASSWORD=secure_pwd - Use secure vaults in production (Azure Key Vault, AWS Secrets Manager, etc.)
- Rotate credentials regularly according to your security policy
- Audit credential usage through application logs
- Never log full credentials - log hashed or masked versions only
Credential Validation
Validation Process
All credentials are validated before submission:
- Service Provider Validation
- Checks if Service Provider ID and Password are non-empty
- Validates format of Service Provider ID
- Ensures credentials match registered provider with ARAMS
- Property User Validation
- Validates property username and password format
- Checks property access permissions for the user
- Verifies property type matches (Farm/Abattoir)
- Test Transaction Validation
- Sends minimal test notification to ARAMS
- Confirms successful authentication
- Validates property accessibility
Validation Implementation
// Property validator ensures property identifier is accessible
public class PropertyValidator : IPropertyValidator<AramsMovementService>
{
public bool Validate(string propertyIdentifier,
ServiceProviderAuthentication serviceProviderAuth)
{
// Property identifier format validation (XX/XXX/XXXX)
if (!IsValidCphFormat(propertyIdentifier))
return false;
// Additional property accessibility checks
return _propertyService.IsPropertyAccessible(propertyIdentifier);
}
private bool IsValidCphFormat(string cph)
{
// Validates CPH format: XX/XXX/XXXX
var parts = cph.Split('/');
return parts.Length == 3
&& int.TryParse(parts[0], out var _)
&& int.TryParse(parts[1], out var _)
&& int.TryParse(parts[2], out var _);
}
}
Error Handling
Authentication-Related Errors
| Error | Cause | Resolution |
|---|---|---|
InvalidCredentialsException |
Service Provider ID or Password incorrect | Verify Service Provider credentials with ARAMS |
PropertyAuthenticationFailed |
Property username or password incorrect | Verify property user credentials with property owner |
PropertyNotAccessible |
User not authorized for this property | Contact ARAMS to verify property access |
InvalidPropertyIdentifier |
CPH format invalid or property doesn’t exist | Check CPH format is XX/XXX/XXXX and property exists |
CredentialsExpired |
Credentials have expired | Request credential reset from ARAMS |
InsufficientPermissions |
User doesn’t have permission for operation type | Request appropriate permissions from ARAMS |
Example Error Handling
try
{
var response = movementService.SubmitMovement(transaction, authentication);
if (!response.Success)
{
switch (response.ErrorCode)
{
case "AUTH001":
logger.LogError("Invalid Service Provider credentials");
return StatusCode(401, "Service Provider authentication failed");
case "AUTH002":
logger.LogError("Invalid Property credentials for {PropertyId}",
transaction.PropertyIdentifier);
return StatusCode(401, "Property authentication failed");
case "AUTH003":
logger.LogError("Insufficient permissions for operation");
return StatusCode(403, "User lacks required permissions");
default:
logger.LogError("Authentication error: {ErrorCode}", response.ErrorCode);
return StatusCode(500, "Authentication error occurred");
}
}
}
catch (AuthenticationException ex)
{
logger.LogError(ex, "Authentication failed: {Message}", ex.Message);
return StatusCode(401, "Authentication failed");
}
Test Environment
Test Environment Endpoints
Farm Service (Test):
https://testws.arams.co.uk/FarmServices/services/
Abattoir Service (Test):
https://testws.arams.co.uk/AbattoirServices/services/
Test Credentials
For testing purposes, contact ARAMS to obtain test credentials:
var testAuthentication = new Authentication
{
ServiceProviderAuth = new ServiceProviderAuthentication
{
Username = "TEST_SP_ID", // Test Service Provider ID
Password = "TEST_SP_PASSWORD",
ProgramName = "TestApplication",
ProgramVersion = "1.0.0",
SchemaVersion = "2.0"
},
PropertyAuth = new PropertyAuthentication
{
PropertyType = "F",
Username = "test_user@test.arams.co.uk",
Password = "test_password"
}
};
Test Property Identifiers
Common test CPH values for testing:
- Farm Test CPH: “00/000/0000” (used for credential validation)
- Abattoir Test CPH: “40/000/0000”
Environmental Configuration
public class AramsSettings
{
public bool IsTestEnvironment { get; set; }
public string GetWebServiceUrl()
{
return IsTestEnvironment
? "https://testws.arams.co.uk/FarmServices/services/"
: "https://webservices.arams.co.uk/FarmServices/services/";
}
public string GetAbattoirServiceUrl()
{
return IsTestEnvironment
? "https://testws.arams.co.uk/AbattoirServices/services/"
: "https://webservices.arams.co.uk/AbattoirServices/services/";
}
}
// Usage in configuration
var settings = new AramsSettings
{
IsTestEnvironment = !hostEnvironment.IsProduction()
};
Testing Credential Validation
[Fact]
public void ValidateCredentials_WithCorrectServiceProviderAuth_ReturnsSuccess()
{
// Arrange
var testAuth = new Authentication
{
ServiceProviderAuth = new ServiceProviderAuthentication
{
Username = "TEST_SP_ID",
Password = "TEST_SP_PASSWORD"
},
PropertyAuth = new PropertyAuthentication
{
PropertyType = "F",
Username = "test_user",
Password = "test_password"
}
};
// Act
var validator = new UserCredentialValidator(_container, _dateTime);
var result = validator.Validate(
testAuth.PropertyAuth.Username,
ref testAuth.PropertyAuth.Password,
testAuth.ServiceProviderAuth);
// Assert
Assert.True(result);
}
[Fact]
public void ValidateCredentials_WithInvalidPassword_ReturnsFalse()
{
// Arrange
var testAuth = new Authentication
{
ServiceProviderAuth = new ServiceProviderAuthentication
{
Username = "TEST_SP_ID",
Password = "INVALID_PASSWORD"
},
PropertyAuth = new PropertyAuthentication
{
PropertyType = "F",
Username = "test_user",
Password = "wrong_password"
}
};
// Act
var validator = new UserCredentialValidator(_container, _dateTime);
var result = validator.Validate(
testAuth.PropertyAuth.Username,
ref testAuth.PropertyAuth.Password,
testAuth.ServiceProviderAuth);
// Assert
Assert.False(result);
}
Last Updated: January 2024
ARAMS API Version: 2.0
Related Documentation: ARAMS Service Overview