Skip to main content

8 posts tagged with "Security"

View all tags

Configuration of Passkeys (WebAuthn) using Amazon Cognito

· 4 min read

I am using Amazon Cognito for user authentication in a file storage API built with AWS SAM. Recently, I added login via passkeys (WebAuthn), so I will summarize the configuration details.

Prerequisites: Required Cognito Settings for Passkeys

To use passkeys with Cognito, the following must all be in place:

RequirementCurrent Configuration
UserPool TierESSENTIALS or higher
Managed Loginv2 (New login UI)
Custom Domainlogin.example.com (Used as Relying Party ID)

Cognito's passkeys will be registered and used through the Managed Login v2 UI. WebAuthn cannot be used with the LITE tier (free), so the ESSENTIALS tier is necessary.

Authentication Flow

Passkey Registration Flow

For the first time, log in with a password and register the passkey from the account settings.

Passkey Login Flow

After registration, authentication can be done directly via the "Sign in with passkey" button.

Configuration Details

The changes made to the template.yaml (SAM template) for adding the passkey amount to just 6 lines.

Before Changes

UserPool:
Type: AWS::Cognito::UserPool
Properties:
# ...
Policies:
PasswordPolicy:
MinimumLength: 8
# ...
MfaConfiguration: "OFF"

After Changes

UserPool:
Type: AWS::Cognito::UserPool
Properties:
# ...
Policies:
PasswordPolicy:
MinimumLength: 8
# ...
SignInPolicy:
AllowedFirstAuthFactors:
- PASSWORD
- WEB_AUTHN # ← Added passkey
MfaConfiguration: "OFF"
WebAuthnRelyingPartyID: login.example.com # ← Specify RP ID
WebAuthnUserVerification: required # ← Require biometric verification

Explanation of Each Parameter

SignInPolicy.AllowedFirstAuthFactors

This is the list of authentication methods that can be used during the first authentication step. With only PASSWORD, it allows password-only authentication; adding WEB_AUTHN allows passkeys as an option.

WebAuthnRelyingPartyID

This is the Relying Party ID (RP ID) for WebAuthn. Passkeys are generated and stored associated with this domain, so it must match the domain serving the actual login page.

In this case, I have directly specified the custom domain login.example.com. If you are using the Cognito default domain (xxx.auth.ap-northeast-1.amazoncognito.com), specify that one.

WebAuthnUserVerification

This defines the required level of user verification when using passkeys.

ValueDescription
requiredRequires biometric authentication or PIN
preferredPrefer user verification but allow even without it
discouragedSkip user verification (no biometric, etc.)

To enhance security, I chose required.

Managed Login UI

In the Managed Login v2 interface, after configuring the passkey, the "Sign in with passkey" button will be automatically added to the login screen. For initial registration, you can add a passkey from the account settings after logging in with a password.

Deployment

sam build
sam deploy --no-confirm-changeset

Since the stack name, region, and parameters are defined in samconfig.toml, there is no need to specify options each time.

Conclusion

The key points for enabling passkeys in Cognito are:

  1. Set to ESSENTIALS tier (LITE does not support WebAuthn)
  2. Use Managed Login v2
  3. Specify a custom domain (or the Cognito default domain) as the RP ID
  4. Add WEB_AUTHN to SignInPolicy.AllowedFirstAuthFactors
  5. Set WebAuthnUserVerification: required to make biometric verification mandatory

With just 6 lines of changes, passkey login has become available. The convenience of Cognito lies in the ability to gradually transition to passkeys while still retaining passwords.

What is CORS? An Explanation of Security for Beginners

· 6 min read

This article explains CORS (Cross-Origin Resource Sharing), a web browser security feature, for beginners, covering "why it's necessary" and "what dangers it entails." Understanding it correctly will enable secure web development.

The Background of the Need for CORS: Same-Origin Policy

In the early 1990s, when JavaScript was incorporated into browsers, the concept of web security was almost nonexistent. At that time, malicious websites could freely access data from other sites, making it easy for session hijacking and data theft to occur.

To solve this problem, a restriction known as the Same-Origin Policy was introduced. This is a simple yet powerful rule that states, "JavaScript loaded from a web page cannot access data from a different origin."

For example, JavaScript loaded from a page at https://www.example.com cannot access data from https://www.bank.com. This ensures that even if a user accesses a malicious site while logged into their bank site, their banking information cannot be stolen.

What is an Origin?

Origin is determined by the following three factors:

  • Protocol: either http:// or https://
  • Host (domain): either example.com or api.example.com
  • Port: either 80 or 8080

For example,

URLProtocolHostPortOrigin
https://www.example.com/pageHTTPSwww.example.com443 (default)https://www.example.com
https://api.example.com/dataHTTPSapi.example.com443 (default)https://api.example.com

Since these are different hosts, they are considered different origins.

What the Same-Origin Policy Prevents

Requests to different origins via JavaScript's XHR (XMLHttpRequest) or Fetch API are restricted.

Example: A malicious script on evil.com

fetch('https://bank.example.com/api/transfer', {
method: 'POST',
body: JSON.stringify({ amount: 1000000 })
});

Without the Same-Origin Policy, JavaScript from a malicious site (evil.com) could send a transfer request while the user is logged into their bank site. Preventing this scenario is the purpose of the Same-Origin Policy.

Why CORS is Necessary

However, modern web design often involves cooperation among multiple origins.

  • Frontend: https://www.example.com
  • API Server: https://api.example.com
  • CDN / Static Files: https://cdn.example.com

These are operated by the same company and are legitimate communications. But if restricted by the Same-Origin Policy, the application would not function.

This is where CORS (Cross-Origin Resource Sharing) comes into play.

What is CORS: Explicitly Allowing Access

CORS is a mechanism by which the server explicitly declares, "requests from this origin are permitted."

By simply returning the following response headers, the browser can relax the restrictions.

Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization

Unless the server says "allowed," the browser will not pass the results of the request back to JavaScript. This achieves cross-origin access while maintaining security.

Security Risks of CORS: Common Configuration Mistakes

Although CORS is convenient, incorrect settings can create security vulnerabilities.

Mistake: Allowing All Origins

Access-Control-Allow-Origin: *

This means, "Anyone from anywhere can access this server."

// JavaScript from https://evil.com
fetch('https://api.example.com/user/profile')
.then(r => r.json())
.then(data => {
// Process to steal user profile information
console.log(data);
});

This is particularly dangerous for requests that include authentication credentials (such as cookies), as a user logged into api.example.com could have their personal information stolen when accessing evil.com.

Half Dangerous: * Prohibited for Requests Including Cookies

fetch('https://api.example.com/user/profile', {
credentials: 'include' // Include cookies
})

When including authentication credentials, Access-Control-Allow-Origin: * cannot be used. You must always specify a specific origin.

Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Credentials: true

Mistake: Allowing User-Specified URLs Directly

// Dangerous implementation example (server-side)
const origin = request.headers.get('Origin');
response.headers.set('Access-Control-Allow-Origin', origin); // Return as is!

This can allow requests from https://evil.com, resulting in a response with Access-Control-Allow-Origin: https://evil.com, which can be exploited.

The correct approach is to prepare a whitelist and allow only those origins.

const allowedOrigins = [
'https://www.example.com',
'https://admin.example.com'
];

if (allowedOrigins.includes(origin)) {
response.headers.set('Access-Control-Allow-Origin', origin);
}

Mistake: Allowing All Headers

Access-Control-Allow-Headers: *

This means "Any header is accepted," allowing injections of malicious data through custom headers.

List only the necessary headers.

Access-Control-Allow-Headers: Content-Type, Authorization

CORS Preflight Request: Browser's Prior Check

For requests other than simple requests (GET, HEAD, POST), the browser automatically sends an OPTIONS method request to check "Is this okay?" This is known as a preflight request.

1. JavaScript tries to send a PUT request

2. The browser automatically sends an OPTIONS preflight request
OPTIONS /api/resource HTTP/1.1
Origin: https://www.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

3. The server responds with "OK"
HTTP 200 OK
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: Content-Type

4. The browser sends the actual PUT request

If the server does not support the OPTIONS method, the preflight will fail, and the actual request will not be sent.

Key Points:

  • Explicitly specify allowed origins in the whitelist
  • Use credentials: true to handle requests including cookie authentication
  • Allow only necessary methods and headers
  • Options preflight request

Common Questions

Q. I encountered a CORS error. Can I allow all origins to resolve it?

A: No. It might work temporarily, but allowing * in a production environment poses a security risk. You need to revisit the server-side settings or redesign the API.

Q. I want to access origins at different ports during local development. Is that okay?

A: Disabling CORS just for the local development environment is acceptable.

Q. Does CORS matter when calling APIs from mobile apps?

A: CORS is a browser security feature, so it does not apply to mobile apps. Instead, you need to implement authentication and authorization using API keys or OAuth.

Summary

PointExplanation
Purpose of CORSAllow cross-origin access while maintaining browser security
Dangerous ConfigurationUsing Access-Control-Allow-Origin: * for APIs requiring authentication
Correct ConfigurationExplicitly specify allowed origins in the whitelist
When Including CookiesMust specify Access-Control-Allow-Credentials: true and a specific origin
PreflightComplex requests like PUT/DELETE require the browser to pre-check with OPTIONS

CORS is not just a "cause of errors," but an important mechanism in web security. Misconfigurations can lead to security incidents, so it must be handled with care.

References

How to create certificates using mkcert on Raspberry Pi for cockpit and configure them on the server (cockpit) and browser

· 2 min read

Operating Environment

The following environment was confirmed for setup.

  • Raspberry Pi 5
  • AlmaLinux

Meaning of Each Certificate

  • raspberrypi.pem: Server certificate (public key) This certificate is an SSL certificate issued for the hostname raspberrypi. Clients such as web browsers use this certificate to verify the authenticity of the server. (This is the one to install on the server)
  • raspberrypi+1.pem: Server certificate (public key) This certificate is an SSL certificate issued for the hostname raspberrypi <IP address>. Same as above.
  • raspberrypi-key.pem: This is the private key corresponding to raspberrypi.pem. Keep it on the server and use it for SSL encryption/decryption. Never leak it to external parties. (This is the one to install on the server)
  • raspberrypi+1-key.pem: This is the private key corresponding to raspberrypi+1.pem. Keep it on the server and use it for SSL encryption/decryption. Never leak it to external parties. Same as above.
  • rootCA.pem: Local root certificate (public key) This is the certificate of the local CA (Certificate Authority) automatically generated by mkcert. Installing this certificate on the client (browser, etc.) allows raspberrypi.pem to be treated as a trusted certificate.
  • rootCA-key.pem: Private key of the local CA This is the private key corresponding to rootCA.pem, used by mkcert to sign server certificates (e.g., raspberrypi.pem). It is used internally by mkcert and usually does not need to be touched.

Certificate Issuance

Certificates are issued using the mkcert command. After issuance, they are placed on the server.

mkcert raspberrypi <IP address>

sudo cp raspberrypi+1-key.pem /etc/cockpit/ws-certs.d/raspberrypi.key
sudo cp raspberrypi+1.pem /etc/cockpit/ws-certs.d/raspberrypi.crt
sudo systemctl restart cockpit

Check the location of the local root certificate

Check the location of the root CA certificate to install on the PC.

mkcert -CAROOT

Copy the root certificate to the PC

Copy the root certificate to the PC.

scp raspberrypi:/home/<USER>/ .local/share/mkcert/rootCA.pem .
cp rootCA.pem rootCA.cer

Register the certificate on Windows

Open rootCA.cer and register the certificate in the certificate store under "Trusted Root Certification Authorities".

Register the certificate on Android terminals

Move rootCA.pem to the device and register it in the settings.

Exploring Local MCP Behavior by Running Commands

· 3 min read

Processing Flow

I asked GitHub Copilot about the processing flow in an LLM client when using MCP.

Below is a sequence diagram.

What's important here are:

  1. ①② Retrieving tool definitions
  2. ④ Sending tool definitions
  3. ⑦ Tool call request
  4. ⑧⑨⑩⑪ Calling the tool
  5. ⑫ Sending the execution result

The parts related to MCP are 1. and 4., while parts 2., 3., and 5. are almost identical to Function Calling.

Calling Tools from the Command Line

Let's use local MCP with standard input.

We'll execute commands using Windows PowerShell.

Retrieving the Tool List

As an example, let's retrieve the tool list for @modelcontextprotocol/server-filesystem.

> @{ jsonrpc = "2.0"; method = "tools/list"; id = 1 } | ConvertTo-Json -Compress | npx @modelcontextprotocol/server-filesystem $HOME | ConvertFrom-Json | ConvertTo-Json -Depth 10
Secure MCP Filesystem Server running on stdio
Allowed directories: [ 'C:\\Users\\hikari' ]
{
"result": {
"tools": [
{
"name": "read_file",
"description": "Read the complete contents of a file from the file system. Handles various text encodings and provides detailed error messages if the file cannot be read. Use this tool when you need to examine the contents of a single file. Only works within allowed directories.",
"inputSchema": {
"type": "object",
"properties": {
"path": {
"type": "string"
}
},
"required": [
"path"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}
},
...
]
}
}

By providing tools/list via standard input, you can retrieve the tool list in JSON format.

Calling a Tool

Let's call a tool based on its information.

> @{ jsonrpc = "2.0"; method = "tools/call"; params = @{name = "read_file"; arguments = @{path = ".gitconfig"}}; id = 2 } | ConvertTo-Json -Compress -Depth 10 | npx @modelcontextprotocol/server-filesystem $HOME | ConvertFrom-Json | ConvertTo-Json -Depth 10
Secure MCP Filesystem Server running on stdio
Allowed directories: [ 'C:\\Users\\hikari' ]
{
"result": {
"content": [
{
"type": "text",
"text": "..."
}
]
},
"jsonrpc": "2.0",
"id": 2
}

How to Japanese the Linux Prompt

· One min read

This post introduces how to Japanese the Linux prompt.

1. Install Japanese Locale

Next, if the Japanese locale does not exist, install it with the following command.

sudo apt update
sudo apt install language-pack-ja

2. Set the Locale

Set the Japanese locale with the following command.

sudo update-locale LANG=ja_JP.UTF8

3. Restart the System

Finally, restart the system. This will reflect the new locale settings.

sudo reboot

With the above steps, the Linux prompt will be Japanese.

How to change the Linux prompt to Japanese

· One min read

This post explains how to localize the prompt on Raspberry Pi.

1. Setting the locale

Set the Japanese locale. Execute the following commands:

  1. Check the box as shown with a space and OK.
  2. Select ja_JP.UTF-8 and OK.
sudo dpkg-reconfigure locales

# [*] ja_JP.UTF-8 UTF-8

2. Reboot

Reboot the system.

sudo reboot

That's all.

How to expose a server on WSL2 to the LAN using SSH tunneling

· 2 min read

Step1. Install OpenSSH Server on WSL

Install OpenSSH Server on WSL2. Also, start the sshd service.

# WSL2 side
sudo apt install openssh-server
sudo service sshd start

Step2. Register the public key on the Windows side

If you have not registered the public key on Windows, run the following command.

# Windows side
ssh-keygent -t ed25519

Next, register the public key on WSL2.

# Windows side
$pubkey = $(cat $HOME\.ssh\id_ed25519.pub)
wsl -- echo $pubkey `| tee -a `$HOME/.ssh/authorized_keys

Step3. Tunnel with SSH

Connect to WSL2 from Windows via SSH.

# Windows side
ssh (wsl -- hostname -I).trim() -g -L8081:localhost:8080

Explanation of the command:

  • (wsl -- hostname -I).trim() retrieves the IP address of WSL2.
  • -g forwards the port to the LAN (accessible from external devices with an address like 192.168.x.x).
  • -L is the local forward option. It forwards the server's port to a local port.
  • 8081 and localhost:8080 mean that accessing http://localhost:8081 will forward to localhost:8080. Here, localhost refers to localhost as seen from the server side.

Step4. Start the server

Start the server that you want to expose on WSL2.

# WSL2 side
ruby -run -e httpd . # Directory listing will be exposed

Step5. Access the server

You can access the service at http://localhost:8081 or http://<IP address displayed by ipcconfig>:8081.

A disadvantage of tunnel connections is that it is tedious to tunnel every time. Although unstable, you can do the same thing by using netsh interface portproxy ~.

My Number Card (Myna Card) - What Have I Used It For?

· 5 min read

This post summarizes how I've used my My Number Card, obtained in 2018, and what conveniences it has brought. I'll also cover the inconvenient aspects.

Things I've Used It For

  1. Printing Certificates at Convenience Stores
    • Copy of Resident Record
    • Certificate of Income

This is convenient because there's no need to specially visit a city hall (or branch office) and wait in line.

  1. Identity Verification
    • Smartphone communication contracts
    • Opening a securities account
    • Opening a bank account
    • Identity verification for "XXXX Pay" services
    • Identity verification for COVID-19 vaccine appointments

In the future, identity verification might become difficult without a My Number Card. Society is becoming less based on trust, so it might be unavoidable. It's good that I don't have to get a driver's license just for ID purposes when I don't drive. Probably about 20% of people are in this situation.

  1. Tax Returns (Kakutei Shinkoku)

I just had to enter numbers into the form and submit it. It's convenient, as it can also calculate medical expense deductions.

  1. Using it as a Health Insurance Card

It's good not to have to carry my health insurance card, but I've encountered problems several times where it couldn't be used due to bugs in the qualification verification system, so it seems best to carry my physical health insurance card just in case. It's convenient that information on medicines prescribed at pharmacies can be checked on MyNa Portal (especially for people with drug allergies). If I use my health insurance card instead of my Myna Card, will it still calculate medical expenses? I'm not sure about that.

  1. Moving-out Notification

Going to the city hall (or branch office) to submit a moving-out notification during the busy period at the end of March is daunting, but you can submit it online using MyNa Portal. The important thing to remember is not to forget the moving-in notification. (By the way, going to a branch office is less crowded than going to the main city/ward office.) It was a hassle to have to reset my My Number PIN when moving in.

  1. Smartphone Electronic Certificate

You can load your My Number electronic certificate onto your smartphone. It might be convenient as you can log in to MyNa Portal card-less.

Dissatisfactions

  1. Smartphone App NFC Even though the electronic certificate is on my smartphone, it always requests NFC. It's inconvenient that the app won't open without NFC being enabled, so I hope for improvement.

  2. My Number is Written on It Having the My Number written on the My Number Card creates a risk if it's lost. Although misuse is hard to imagine. I wish it were numberless like a credit card.

  3. Monochrome Photo The photo embedded in the My Number Card is monochrome. Why wasn't it in color?

  4. Troublesome Renewal Due to electronic certificate security, renewals are every 5 years. However, the card's validity period is 10 years. What? It seems it might or might not be improved.

  5. Hospitals Where the Card Cannot Be Used It seems the government provides some subsidies, so I hope they will support it.

  6. Too Many PIN Types There are four types of PINs. I wish there were just one, but is it difficult due to security? I don't know.

  7. Unstylish Card Design I wish it would emulate the design of a radio operator's license.

Probably Misunderstood Things

There are many off-base criticisms of the My Number Card, so I'll summarize them. Please understand the system before criticizing.

  1. Personal Information Linked from the My Number Card is Extracted This is partially correct. The My Number Card itself only contains basic personal information like address, name, gender, and date of birth. It probably contains less information than a driver's license. To view information linked to the My Number Card, you need to open the linked site and authenticate using the My Number Card. Linked information cannot be viewed without the My Number Card and its PIN. Of course, if you write the PIN on the card and then lose it, various pieces of personal information could be extracted. This point is similar to a cash card.

  2. The PIN is only 4 digits, and security is weak It's incorrect that security is weak. Consider logging into SNS on a computer; you can log in with an ID and password. On SNS, the ID is easily known, so you can log in if you have the password. No matter how complex the password, it's a single-factor authentication. On the other hand, the My Number Card uses two-factor authentication: possession of the card + knowledge of the PIN. The reason Windows and other systems allow logging in with a PIN is that two-factor authentication (possession + memory) is said to be more secure than single-factor authentication using a complex password.

  3. Errors in Health Insurance Card Linkage This is a linkage error by the health insurance association, a human error. The My Number Card is merely a personal authentication mechanism and is not the problem itself. However, there is an argument to be made about how to deal with errors in linkage by health insurance associations. Health insurance information can be checked on MyNa Portal, so it's advisable to check it once.

  4. 100% burden at the counter without a My Number Card is outrageous As before, you can receive a refund by processing it through your health insurance association. However, it seems they will introduce a "qualification certificate" system, which defeats the purpose.