The problem
File sharing shouldn't require teaching users how to navigate the S3 console, install desktop clients, or run CLI commands. You just want to hand someone a URL, let them log in, and let them upload/download files from a specific folder — with proper access control.
Our customer had on-prem Windows file storage that needed to be accessible to distributed team members via a browser. No FTP servers, no VPN required for end users, no training on AWS console. Just a clean, branded portal.
Architecture
The end-to-end flow: on-prem files sync to S3 via DataSync over Site-to-Site VPN. The Transfer Family Web App provides browser-based access. IAM Identity Center handles SSO. S3 Access Grants control per-user permissions. CloudFront delivers it on a custom domain.
Architecture — On-prem to S3 via DataSync, Transfer Family Web App with IAM Identity Center, CloudTrail/CloudWatch/KMS
- SAML / OIDC identity provider
- Built-in directory
- Email invitations
- Per-prefix access control
- Identity-aware (user/group)
- No bucket policies needed
AWS services used
| Service | Role |
|---|---|
| Transfer Family Web App | Managed file transfer portal (no-code) |
| S3 + S3 Access Grants | Storage + per-prefix identity-aware permissions |
| IAM Identity Center | SSO authentication for workforce users |
| DataSync + Site-to-Site VPN | On-prem to S3 sync |
| CloudFront + Route 53 | Custom domain for branded access |
| KMS / CloudTrail / CloudWatch | Encryption, audit logging, monitoring |
Setup
IAM Identity Center
Set up IAM Identity Center with directory users. The web app integrates directly — users get an email invitation, authenticate through SSO, and land in the file manager.
Create the Web App
In the Transfer Family console → Web apps → Create web app. That's it.
Transfer Family Web App configuration — endpoint, IAM role, units, customization
- Endpoint: Public, Dual-stack
- IAM Role:
AWSTransferWebAppIdentityBearer-us-east-1— trust policy allowstransfer.amazonaws.comtosts:AssumeRole+sts:SetContext - Units: 1 (up to 250 concurrent sessions)
- Customization: Added logo, page title
IAM Role Trust Policy
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "transfer.amazonaws.com" },
"Action": ["sts:AssumeRole", "sts:SetContext"]
}]
}
S3 Access Grants
This is where the real power is. Instead of bucket policies, you create grants scoped to specific S3 prefixes per identity group. No IAM user keys. No per-user bucket policies. Identity-aware access at the prefix level.
| Grant Scope | Permission | Grantee |
|---|---|---|
s3://bucket-name/* | Read, Write | Directory identity group |
s3://bucket-name-archive/* | Read | Directory identity group |
S3 Access Grants — per-prefix, identity-aware permissions
Custom domain via CloudFront
The default Transfer Family Web App URL looks like webapp-1622a11999354a5da.transfer-webapp.us-east-1.on.aws — not something you'd share with a customer.
Fix:
- Deploy CloudFront distribution using the AWS-provided CloudFormation template
- Set custom URL to the customer's branded domain
- ACM certificate + Route 53 alias → CloudFront
- Update S3 bucket CORS to allow the custom origin
CloudFront distribution with custom domain and ACM certificate
AllowedOrigins in the S3 CORS policy when switching to the custom domain.S3 CORS configuration
[{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"AllowedOrigins": ["https://your-custom-domain.com"],
"ExposeHeaders": ["ETag", "x-amz-request-id"]
}]
End user experience
Users see only their authorized S3 locations with permissions listed. They can upload (up to 160 GB), download, copy, create folders, delete, and search — all through the browser.
Web App landing — shows authorized S3 locations with permission levels
File manager UI — upload, download, copy, delete, create folders
Files are transferred over HTTPS with TLS, multipart uploads for large files, and CRC32 end-to-end integrity checks. No desktop client needed.
Disaster recovery
Since this is fully managed — no servers, no infrastructure state to maintain — DR is trivial.
S3 Cross-Region Replication (CRR) keeps a live replica in a secondary region. If the primary goes down:
- Launch a new Transfer Family Web App in the DR region (minutes)
- Point it to the replicated S3 bucket
- IAM Identity Center is already global — users just work
- Update CloudFront origin or Route 53 failover record
Cost breakdown
| Component | Pricing |
|---|---|
| Web app unit | ~$0.30/hr (250 concurrent sessions) |
| S3 Access Grants | Free (part of S3) |
| IAM Identity Center | Free tier |
| Data transfer | Standard S3 + CloudFront rates |
~$220/month running 24/7. Stop the web app when not needed to cut costs.
Takeaways
- Zero custom code — this is a managed AWS service, not a custom portal. Create in console, assign users, done.
- S3 Access Grants are the unlock — per-prefix, identity-aware permissions without managing bucket policies per user.
- Custom domain via CloudFront is worth it — users trust branded URLs.
- CORS will trip you up — update
AllowedOriginswhen switching to custom domain. - Managed = simple DR — CRR + new web app in another region = back online in minutes.