100 Exercises / System Development / 100 Exercise on System Development

Introduction to Certification and Authorization Management in Manufacturing | 10 Steps to Learn JWT, RBAC, and API Protection

Protecting Factory Operations Systems by Protecting ‘Who Can Do What’ — 10 Exercises on Authentication and Permission Management

Focusing on Work Performance and Quality Record System for manufacturing sites, we will provide a comprehensive overview of authentication and authorization, login, password protection, JWT, frontend login status, logout, role design, screen control, and API protection. The purpose is not to add a login function. While maintaining operator operability, it is about restricting important operations such as changing quality judgments and updating the master system to the appropriate personnel, thereby creating an auditable business foundation.

[!NOTE] This material is a notebook previously used by Surikoubo (or personally by the representative, Kazuyama), and has been reconstructed, edited, and published with the company’s permission.
All data listed is fictional and has no relation whatsoever to real companies, factories, or figures.

Introduction: Practical Challenges in Manufacturing Covered in This Article

In manufacturing systems, the same screen may be used by workers, team leaders, quality assurance personnel, and system administrators. However, the information you can view and the actions you can perform vary by role. For example, even if workers can register their own line’s performance, they must not be able to change confirmed quality judgments or user permissions.

The challenge this time is to simultaneously establish the following three points for the factory’s work performance and quality record system.

  • Identity verification: Confirm that the person operating the operation is a registered person
  • least privilege: Allow only the necessary operations according to your job, line of affiliation, and target data
  • Business Continuity: Shared devices, shift work, and ensuring safe use even with communication delays

From here on, we generate hypothetical users, login attempts, API access, and sessions in Python, and check design decisions using tables and graphs.

Common situations on site

  • On a shared device within the factory, the previous user’s login status remains, and achievements are registered as a different person.
  • The design allows anyone to log in to use all functions, allowing anyone to change quality judgments and master settings
  • Passwords are stored only in plain text or as fast hashes, increasing the risk of leaks.
  • The admin button is hidden on the screen, but you can operate it directly by calling the API.
  • Only the JWT signature is checked, without checking the expiration date, issuer, or intended use.
  • Even after retirement, transfer, or support work, old authority and sessions remain
  • Authentication failures are collectively recorded as “errors,” making it impossible to distinguish between attacks, operational errors, and account suspensions.

Why is this issue so difficult to judge?

Authentication and privilege management are not a one-axis issue where strengthening security is always better. Short automatic logouts reduce impersonation while increasing the burden of repeatedly logging in after removing gloves. The more detailed the authority, the closer it approaches the minimum privileges, but transfers and maintenance for support shifts become more complex.

Furthermore, it is necessary to consider the following layers separately.

  1. Identity verification: Verify identity with passwords and multi-factor authentication
  2. Session Management: Carry over the status of ‘Confirmed Completed’ for a limited time
  3. Approval: Each time, it is determined whether the person is allowed to operate on the target data.
  4. Audit: Track who, when, what, and who was allowed or denied

You need to design screen usability, API security, HR and organizational information updates, and audit logs all in one, tracking not only success rates but also reasons for rejection and deviation rates as KPIs.

Overview of Exercise covered this time

No.ThemeKey Points to Check in the Factory Operations System
051Certification and AuthorizationSeparating identity verification from permission to operate
052Login screenBalancing safety and on-site completion rates
053PasswordAvoid storing plain text and use slow hashes with salt
054How JWT WorksUnderstanding the structure and validation items of signed tokens
055Login APITurn authentication results into consistent API responses
056Front Condition ManagementClearly indicate unconfirmed, confirmed, or authenticated
057LogoutDesigning device-side deletion and server-side expiration
058Roll separationSeparating operations for administrators and general users
059screen switchPresent only paths that match your authority
060API ProtectionAuthenticate and authorize all protected APIs

Preparing the Python environment

Generate and aggregate fictional data using numpy and pandas, and visualize it in matplotlib. For JWT structure verification and password hashing examples, use the Python standard library. Keep the random number seed fixed, and make sure the aggregate result does not change even if you rerun.

%matplotlib inline
%config InlineBackend.figure_format = 'svg'

import sys
import json
import base64
import hashlib
import hmac
from datetime import datetime, timezone

import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import japanize_matplotlib

SEED = 6051
rng = np.random.default_rng(SEED)
pd.set_option("display.max_columns", 30)
pd.set_option("display.width", 140)

print(f"Python     : {sys.version.split()[0]}")
print(f"numpy      : {np.__version__}")
print(f"pandas     : {pd.__version__}")
print(f"matplotlib : {matplotlib.__version__}")
print(f"random seed: {SEED}")
Python     : 3.13.1
numpy      : 2.5.1
pandas     : 3.0.3
matplotlib : 3.11.0
random seed: 6051

Creation of Fictional Data

Create 120 users working on three lines, 1,500 login attempts, 2,400 API accesses, and 180 active sessions. Users are assigned roles such as worker, team leader, quality assurance, and administrator.

Logs intentionally include incorrect passwords, incomplete MFA, suspended accounts, expired tokens, invalid signatures, incomplete roles, and off-line access. This is not a real certification log, but fictitious data for design review and KPI calculations.

roles = ["worker", "squad leader", "Quality Assurance", "administrator"]
role_prob = [0.63, 0.20, 0.12, 0.05]
n_users = 120

users = pd.DataFrame({
    "user_id": [f"U{i:03d}" for i in range(1, n_users + 1)],
    "role": rng.choice(roles, n_users, p=role_prob),
    "home_line": rng.choice(["No.1Line", "No.2Line", "No.3Line"], n_users),
    "account_status": rng.choice(["active", "locked", "disabled"], n_users, p=[0.92, 0.05, 0.03]),
    "mfa_required": rng.random(n_users) < 0.28,
})

n_login = 1500
login_attempts = pd.DataFrame({
    "attempt_id": [f"L{i:05d}" for i in range(1, n_login + 1)],
    "attempted_at": pd.Timestamp("2026-06-01") + pd.to_timedelta(rng.integers(0, 30 * 24 * 60, n_login), unit="m"),
    "user_id": rng.choice(users["user_id"], n_login),
    "device": rng.choice(["Shared tablet", "OfficePC", "Handy device"], n_login, p=[0.52, 0.28, 0.20]),
    "password_ok": rng.random(n_login) < 0.94,
    "mfa_completed": rng.random(n_login) < 0.965,
    "duration_sec": np.maximum(3, rng.lognormal(mean=2.9, sigma=0.48, size=n_login)).round(1),
})
login_attempts = login_attempts.merge(users[["user_id", "account_status", "mfa_required"]], on="user_id", how="left")
login_attempts["failure_reason"] = np.select(
    [
        login_attempts["account_status"].eq("disabled"),
        login_attempts["account_status"].eq("locked"),
        ~login_attempts["password_ok"],
        login_attempts["mfa_required"] & ~login_attempts["mfa_completed"],
    ],
    ["Suspended Account", "On lock", "Password mismatch", "MFAincomplete"],
    default="Success",
)
login_attempts["success"] = login_attempts["failure_reason"].eq("Success")

endpoint_rules = pd.DataFrame({
    "endpoint": ["GET /work-orders", "POST /results", "PUT /quality-judgments", "GET /audit-logs", "POST /users"],
    "required_role": ["Worker or above", "Worker or above", "Quality Assurance and More", "administrator", "administrator"],
    "allowed_roles": [
        roles,
        roles,
        ["Quality Assurance", "administrator"],
        ["administrator"],
        ["administrator"],
    ],
})
n_access = 2400
api_access = pd.DataFrame({
    "request_id": [f"R{i:05d}" for i in range(1, n_access + 1)],
    "user_id": rng.choice(users["user_id"], n_access),
    "endpoint": rng.choice(endpoint_rules["endpoint"], n_access, p=[0.38, 0.31, 0.15, 0.09, 0.07]),
    "target_line": rng.choice(["No.1Line", "No.2Line", "No.3Line"], n_access),
    "token_present": rng.random(n_access) < 0.975,
    "signature_valid": rng.random(n_access) < 0.992,
    "token_expired": rng.random(n_access) < 0.035,
})
api_access = (api_access
    .merge(users[["user_id", "role", "home_line", "account_status"]], on="user_id", how="left")
    .merge(endpoint_rules[["endpoint", "allowed_roles"]], on="endpoint", how="left"))
api_access["identity_verified"] = (
    api_access["token_present"] & api_access["signature_valid"] & ~api_access["token_expired"] & api_access["account_status"].eq("active")
)
api_access["role_allowed"] = api_access.apply(lambda r: r["role"] in r["allowed_roles"], axis=1)
api_access["scope_allowed"] = api_access["role"].isin(["Quality Assurance", "administrator"]) | api_access["home_line"].eq(api_access["target_line"])
api_access["permission_granted"] = api_access["identity_verified"] & api_access["role_allowed"] & api_access["scope_allowed"]

n_sessions = 180
sessions = pd.DataFrame({
    "session_id": [f"S{i:04d}" for i in range(1, n_sessions + 1)],
    "user_id": rng.choice(users["user_id"], n_sessions),
    "device": rng.choice(["Shared tablet", "OfficePC", "Handy device"], n_sessions, p=[0.55, 0.27, 0.18]),
    "age_min": rng.integers(1, 721, n_sessions),
    "revoked": rng.random(n_sessions) < 0.08,
})

display(users.head())
print(f"user: {len(users):,}name / Login attempt: {len(login_attempts):,}records / APIAccess: {len(api_access):,}records / Session: {len(sessions):,}records")
user_id role home_line account_status mfa_required
0 U001 worker No.1Line active False
1 U002 worker No.3Line locked False
2 U003 squad leader No.3Line active True
3 U004 worker No.2Line active True
4 U005 worker No.2Line active False
Users: 120 / Login attempts: 1,500 / API access: 2,400 / Sessions: 180

No.051: Understanding the Difference Between Certification and Authorization

Meaning in Practice

Authentication (Authentication) is about confirming “who the person is,” and Authorization (Authorization) is about “what that person is allowed to do.” Even logged-in workers may not be allowed to finalize quality judgments or add users. At the factory, approval is required to include the assigned line and the target equipment.

Approach to Analysis and Modeling

The permission determination for API request ii is expressed by the following logical product.

Ai=IiRiSiA_i = I_i \land R_i \land S_i

IiI_i indicates identity verification, RiR_i indicates holding the required role, and SiS_i indicates the target line or other scope. If even one of these is false, we will reject them and record the reason in the audit log.

Check with Python

auth_funnel = pd.DataFrame({
    "Judgment Stage": ["wholeAPIRequest", "Identity verified", "Required rolls available", "Within the target scope", "final permission"],
    "number_of_cases": [
        len(api_access),
        int(api_access["identity_verified"].sum()),
        int((api_access["identity_verified"] & api_access["role_allowed"]).sum()),
        int((api_access["identity_verified"] & api_access["scope_allowed"]).sum()),
        int(api_access["permission_granted"].sum()),
    ],
})
auth_funnel["full_requirement_ratio_%"] = (auth_funnel["number_of_cases"] / len(api_access) * 100).round(1)
display(auth_funnel)

fig, ax = plt.subplots(figsize=(8, 4))
ax.bar(auth_funnel["Judgment Stage"], auth_funnel["number_of_cases"], color="#2878B5")
ax.set_title("APIRequest Authentication and Authorization Funnel")
ax.set_xlabel("Judgment Stage")
ax.set_ylabel("Number of Required Items")
ax.grid(axis="y", alpha=0.3)
plt.xticks(rotation=20)
plt.tight_layout()
plt.show()
Judgment Stage number_of_cases full_requirement_ratio_%
0 wholeAPIRequest 2400 100.0
1 Identity verified 1903 79.3
2 Required rolls available 1325 55.2
3 Within the target scope 905 37.7
4 final permission 677 28.2

svg

Reading the results

Even after passing identity verification, there are requests that are rejected due to role or area of responsibility assessment. This is not a failure but the result of minimal privilege working. In practice, we do not focus solely on improving success rates; instead, we separate “failed identity verification,” “insufficient roles,” and “outside of responsibility,” and check whether legitimate tasks are excessively rejected.

No.052: Creating a Login Screen

Meaning in Practice

The login screen serves as both the entry point for identity verification and the entry point to start on-site work. On shared devices, security measures such as not leaving candidate user IDs, not displaying passwords on screens or logs, and controlling repeated failures are necessary. On the other hand, we also check whether the burden of MFA or re-entry does not delay the start of work during rotations.

Approach to Analysis and Modeling

By device, login success rate, median completion time, 95th percentile, and failure reasons are measured. Since the average value alone overlooks the issue of some users stopping for long periods, we use the hem side indicators together.

Check with Python

login_kpi = (login_attempts.groupby("device")
    .agg(
        number_of_trials=("attempt_id", "size"),
        success_rate_pct=("success", lambda s: s.mean() * 100),
        center_finishes_seconds=("duration_sec", "median"),
        p95_is_finished_instant=("duration_sec", lambda s: s.quantile(0.95)),
    )
    .round(1))
failure_counts = login_attempts.loc[~login_attempts["success"], "failure_reason"].value_counts()
display(login_kpi)
display(failure_counts.rename("number_of_cases").to_frame())

fig, ax = plt.subplots(figsize=(8, 4))
ax.bar(failure_counts.index, failure_counts.values, color="#D9534F")
ax.set_title("Breakdown of login failure reasons")
ax.set_xlabel("Reason for failure")
ax.set_ylabel("number_of_trials")
ax.grid(axis="y", alpha=0.3)
plt.tight_layout()
plt.show()
number_of_trials success_rate_pct center_finishes_seconds p95Finished seconds
device
Handy device 313 76.7 18.1 40.0
OfficePC 411 79.3 18.4 39.2
Shared tablet 776 79.5 18.1 41.5
number_of_cases
failure_reason
On lock 127
Suspended Account 103
Password mismatch 73
MFAincomplete 14

svg

Reading the results

By breaking down the reasons for failure, you can distinguish between issues that should be improved with password input support and those that require account verification by administrators. It is effective to return standard messages on the screen that prevent attackers from guessing the registration status, while leaving detailed reasons in the server-side audit logs. If the device-specific p95 is long, review including device placement and MFA methods.

No.053: Handling Passwords Securely

Meaning in Practice

Passwords are not saved in a way that can be recovered. To prevent users with the same password from being identified collectively in the event of a leak, a dedicated hash system is used to add salt for each user and slow down the brute-force process. It is also important to protect communications with TLS and not leave passwords on app logs, analytics platforms, or inquiry forms.

Approach to Analysis and Modeling

In this notebook, the standard library PBKDF2 will be used to explain the mechanism. In actual systems, implementations such as Argon2id, scrypt, bcrypt, PBKDF2, etc., provided by the organization’s standards and usage frameworks are selected, and the number of iterations and other factors are regularly reviewed. SALT is not confidential information, but it is unique to each user.

Check with Python

def pbkdf2_hash(password: str, salt: bytes, iterations: int = 210_000) -> str:
    digest = hashlib.pbkdf2_hmac("sha256", password.encode("utf-8"), salt, iterations)
    return base64.b64encode(digest).decode("ascii")

sample_password = "TrainingOnly-Example!"
password_demo = pd.DataFrame([
    {"user": "U001", "salt": "factory-salt-001", "hashLead": pbkdf2_hash(sample_password, b"factory-salt-001")[:20]},
    {"user": "U002", "salt": "factory-salt-002", "hashLead": pbkdf2_hash(sample_password, b"factory-salt-002")[:20]},
])
password_demo["Same password"] = True
display(password_demo)
print("Even with the same passwordsaltBecause of these differences, the saved hashes do not match.")
user salt hashLead Same password
0 U001 factory-salt-001 qfsoyzYFWurabZUVwCRL True
1 U002 factory-salt-002 h7aDP+vuWGCBCrLNvu+1 True
Even with the same password, the salt values differ, so the stored hashes do not match.

Reading the results

Even with the same password, the hash value will change if the salt is different. During verification, the input values are hashed with the same settings as the saved salt, and constant-time comparisons are performed. The number of sample iterations is not set as the production standard, but is determined based on the performance of the running environment, adoption methods, and the latest internal standards. When resetting your password, you need to verify your identity, revoke existing sessions, and record audits.

No.054: Understanding How JWT Authentication Works

Meaning in Practice

JWT is used as a signed token for the API to transfer user information. A typical JWT consists of three parts of the header.payload.signature, and the payload is not encrypted but is represented by a Base64 URL. Therefore, personal or confidential information must not be casually disclosed.

Approach to Analysis and Modeling

APIs verify not only signatures but also token IDjti iss issuer, recipient, aud, and token exp at least the expiration date. Even if JWT is enabled, separate authorization for the target operation is required. It also separates the roles of short-access tokens and update tokens, which are managed more strictly.

Check with Python

def b64url(data: bytes) -> str:
    return base64.urlsafe_b64encode(data).rstrip(b"=").decode("ascii")

header = {"alg": "HS256", "typ": "JWT"}
payload = {
    "sub": "U042", "role": "squad leader", "iss": "factory-auth",
    "aud": "work-api", "iat": 1782860400, "exp": 1782861300, "jti": "demo-jti-001"
}
secret = b"not-for-production-demo-secret"
unsigned = f"{b64url(json.dumps(header, separators=(',', ':')).encode())}.{b64url(json.dumps(payload, ensure_ascii=False, separators=(',', ':')).encode())}"
signature = b64url(hmac.new(secret, unsigned.encode(), hashlib.sha256).digest())
token = f"{unsigned}.{signature}"

parts = pd.DataFrame({
    "part": ["header", "payload", "signature"],
    "Character count": [len(x) for x in token.split(".")],
    "Role": ["Method and Type", "Regarding users and expiration dates,claims", "Tamper detection"],
})
display(parts)
print("JWTExample (at the beginning80Text):", token[:80] + "...")
print("payload:", payload)
part Character count Role
0 header 36 Method and Type
1 payload 164 Regarding users and expiration dates,claims
2 signature 43 Tamper detection
JWT example (first 80 characters): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJVMDQyIiwicm9sZSI6IuePremVtyIsIml...
payload: {'sub': 'U042', 'role': 'Class Leader', 'iss': 'factory-auth', 'aud': 'work-api', 'iat': 1782860400, 'exp': 1782861300, 'jti': 'demo-jti-001'}

Reading the results

Since the contents of the payload can be read without a decryption key, JWT is not a “secret container.” Signatures detect tampering but do not automatically prevent the misuse of stolen valid tokens. Combine TLS, short expiration dates, secure storage locations, key rotation, and expiration management as needed. The algorithm does not rely solely on the received token; instead, the server-side fixes the permission method.

No.055: Creating a Login API Using JWT

Meaning in Practice

The login API verifies credentials and issues tokens only on successful occasions. If you externally separate inconsistent passwords and unregistered users externally on a failed mission, it may be used for account enumeration. Separate the amount of information from external responses and internal audit logs.

Approach to Analysis and Modeling

State transitions include “Input Validation → Rate Limit → Credential Verification → Account Status Verification → MFA → Token Issuance.” Measure failure rates at each stage and maintain consistent information on HTTP status, error codes, and audit events. Avoid cramming excessive permission information into the token body and design delays in reflecting changes.

Check with Python

def mock_login_api(user_exists: bool, password_ok: bool, account_status: str, mfa_ok: bool) -> dict:
    if not user_exists or not password_ok:
        return {"status": 401, "public_code": "INVALID_CREDENTIALS", "token_issued": False}
    if account_status != "active":
        return {"status": 403, "public_code": "ACCOUNT_UNAVAILABLE", "token_issued": False}
    if not mfa_ok:
        return {"status": 401, "public_code": "MFA_REQUIRED", "token_issued": False}
    return {"status": 200, "public_code": "OK", "token_issued": True}

login_api_cases = pd.DataFrame([
    {"Case": "normal", **mock_login_api(True, True, "active", True)},
    {"Case": "Password mismatch", **mock_login_api(True, False, "active", True)},
    {"Case": "UnregisteredID", **mock_login_api(False, False, "active", True)},
    {"Case": "Suspended Account", **mock_login_api(True, True, "disabled", True)},
    {"Case": "MFAincomplete", **mock_login_api(True, True, "active", False)},
])
display(login_api_cases)
Case status public_code token_issued
0 normal 200 OK True
1 Password mismatch 401 INVALID_CREDENTIALS False
2 UnregisteredID 401 INVALID_CREDENTIALS False
3 Suspended Account 403 ACCOUNT_UNAVAILABLE False
4 MFAincomplete 401 MFA_REQUIRED False

Reading the results

If you use the same external code for unregistered IDs and inconsistent passwords, it becomes harder for users to guess whether they have registered. Meanwhile, to enable operations staff to investigate the cause, internal records include correlation ID, time, device, and determination stage. Methods such as returning tokens to the response body or using cookies with Secure, HttpOnly, or SameSite attributes should be chosen according to your browser configuration and threat model.

No.056: Managing Login Status on the Frontend

Meaning in Practice

The frontend distinguishes not only simple loggedIn=True/False but also during initial verification, authentication, expired, renewal, and authentication failure. This is to avoid accidental actions such as briefly displaying the admin screen during initial checks or leaving expired user information behind it.

Approach to Analysis and Modeling

Treat the certified state as a finite state machine. Define the allowed transitions for events, associating screen display, side effects, and the next operation. Do not confuse the token itself with the display state; limit storage location and update processing.

Check with Python

transitions = {
    ("unconfirmed", "App launch"): "confirming",
    ("confirming", "Session Valid"): "Authenticated",
    ("confirming", "No sessions"): "Uncertified",
    ("Authenticated", "Deadline approaching"): "updating",
    ("updating", "Update successful"): "Authenticated",
    ("updating", "Update failure"): "expired",
    ("Authenticated", "Logout"): "Uncertified",
}
events = ["App launch", "Session Valid", "Deadline approaching", "Update successful", "Deadline approaching", "Update failure"]
state = "unconfirmed"
state_log = []
for event in events:
    next_state = transitions.get((state, event), "improper migration")
    state_log.append({"Current Status": state, "Events": event, "Next state": next_state})
    state = next_state

state_log = pd.DataFrame(state_log)
display(state_log)
Current Status Events Next state
0 unconfirmed App launch confirming
1 confirming Session Valid Authenticated
2 Authenticated Deadline approaching updating
3 updating Update successful Authenticated
4 Authenticated Deadline approaching updating
5 updating Update failure expired

Reading the results

By explicitly indicating state transitions, you can test behaviors such as “not displaying the protected screen during confirmation” or “avoiding input input and guiding users to re-login if the update fails.” The state of the frontend is intended to enhance the user experience and is not a reliable basis for authorization. On the API side, tokens and permissions are verified for each request.

No.057: Implementing Logout Processing

Meaning in Practice

Logging out is especially important on shared tablets. Simply deleting user information in the browser may leave stolen update tokens or server-side sessions active. Design explicit logouts, inactive timeouts, device loss, and password changes as separate expiration events.

Approach to Analysis and Modeling

The risk level of the session is evaluated based on a combination of shared devices, long elapsed periods, and invalid periods not reflected. Server management sessions tend to expire immediately, while self-contained JWTs combine short expiration dates, renewal token removal, and jti rejection lists.

Check with Python

sessions["shared_device"] = sessions["device"].eq("Shared tablet")
sessions["stale"] = sessions["age_min"] > 240
sessions["risk_score"] = 2 * sessions["shared_device"].astype(int) + 2 * sessions["stale"].astype(int) + 3 * (~sessions["revoked"]).astype(int)

logout_policy = pd.DataFrame({
    "policy": ["Delete only on the device side", "Renewing tokens", "All sessions expired"],
    "Number of sessions that can remain after losing a device": [int((~sessions["revoked"]).sum()), int((~sessions["revoked"] & ~sessions["stale"]).sum()), 0],
})
display(sessions.sort_values("risk_score", ascending=False).head(8)[["session_id", "device", "age_min", "revoked", "risk_score"]])
display(logout_policy)
session_id device age_min revoked risk_score
54 S0055 Shared tablet 457 False 7
44 S0045 Shared tablet 379 False 7
72 S0073 Shared tablet 477 False 7
138 S0139 Shared tablet 435 False 7
67 S0068 Shared tablet 616 False 7
66 S0067 Shared tablet 353 False 7
140 S0141 Shared tablet 603 False 7
64 S0065 Shared tablet 312 False 7
policy Number of sessions that can remain after losing a device
0 Delete only on the device side 165
1 Renewing tokens 49
2 All sessions expired 0

Reading the results

Deleting only on the device side does not disable separately copied credentials. Especially on shared devices, a short no-operation period and explicit logout are used together, and the user’s name is clearly displayed during the transition. However, to ensure that uniform timeouts during work do not hinder safe work, we verify process boundaries, speed of re-authentication, and retention of input information on-site.

No.058: Separate administrators from regular users

Meaning in Practice

Since administrators can change users and permissions, they are not treated the same as regular business accounts. Assign operations to roles such as workers, team leaders, quality assurance, and managers, reducing the daily use of administrator privileges. Temporary promotions in emergencies will be subject to approval and a deadline.

Approach to Analysis and Modeling

With RBAC (Role-Based Access Control), instead of assigning a large number of individual permissions to users, permissions are consolidated into job roles. Furthermore, narrow down the scope by attributes such as affiliated line, equipment, and factory. The authority table should be in a format that business managers and information systems can jointly review.

Check with Python

permission_matrix = pd.DataFrame({
    "operation": ["Work Instructions Viewing", "Record Registration", "Performance Approval", "Quality Assessment Confirmed", "Audit Log Viewing", "User management"],
    "worker": [1, 1, 0, 0, 0, 0],
    "squad leader": [1, 1, 1, 0, 0, 0],
    "Quality Assurance": [1, 0, 0, 1, 0, 0],
    "administrator": [1, 0, 0, 0, 1, 1],
}).set_index("operation")
display(permission_matrix.replace({1: "permission", 0: "refusal"}))

fig, ax = plt.subplots(figsize=(7, 4.5))
im = ax.imshow(permission_matrix.T, cmap="Blues", vmin=0, vmax=1, aspect="auto")
ax.set_title("Role-specific operation permission matrix")
ax.set_xlabel("business operation")
ax.set_ylabel("Roll")
ax.set_xticks(range(len(permission_matrix.index)), permission_matrix.index, rotation=30, ha="right")
ax.set_yticks(range(len(permission_matrix.columns)), permission_matrix.columns)
ax.grid(False)
plt.tight_layout()
plt.show()
worker squad leader Quality Assurance administrator
operation
Work Instructions Viewing permission permission permission permission
Record Registration permission permission refusal refusal
Performance Approval refusal permission refusal refusal
Quality Assessment Confirmed refusal refusal permission refusal
Audit Log Viewing refusal refusal refusal permission
User management refusal refusal refusal permission

svg

Reading the results

This is a design example that limits all business operations to administrators and is limited to management functions. By avoiding the ‘I can do anything because I’m an administrator,’ you can minimize the impact of misoperations and account compromises. In practice, according to the division of duties, we add mutual checks and balances that do not treat applicants and approvers as the same person, automatic reflection of transfer dates, and quarterly authority inventory.

No.059: Switching Screens Displayed by Permissions

Meaning in Practice

By hiding menus that do not match permissions, users can focus on the tasks they need. However, hiding the screen is not a security authorization. To prevent direct URL input or API calls from developer tools, server-side checks are mandatory.

Approach to Analysis and Modeling

Necessary permissions are declared for each route, and display is decided based on the inclusion relationship with the set of permissions of logged-in users. 403 Forbidden doesn’t just show a blank screen; it shows the lack of permission, the application destination, and the path back to work.

Check with Python

route_rules = pd.DataFrame({
    "route": ["/work-orders", "/results/new", "/approvals", "/quality", "/admin/audit", "/admin/users"],
    "menu_label": ["work instruction", "Record Entry", "Performance Approval", "Quality Assessment", "Audit Log", "User management"],
    "allowed_roles": [roles, roles, ["squad leader"], ["Quality Assurance"], ["administrator"], ["administrator"]],
})

visibility = pd.DataFrame(index=route_rules["menu_label"], columns=roles)
for _, row in route_rules.iterrows():
    for role in roles:
        visibility.loc[row["menu_label"], role] = "display" if role in row["allowed_roles"] else "hide"
display(visibility)
worker squad leader Quality Assurance administrator
menu_label
work instruction display display display display
Record Entry display display display display
Performance Approval hide display hide hide
Quality Assessment hide hide display hide
Audit Log hide hide hide display
User management hide hide hide display

Reading the results

By organizing menus by role, you can present only the quality judgments necessary for quality assurance without showing the management menu to workers. Display control and API authorization can reduce discrepancies when generated from the same permission definition, but the final decision always rests with the API. After changing permissions, decide on the timing of re-acquisition or session updates so that old menus are not retained.

No.060: Protecting Authenticated APIs

Meaning in Practice

Protected APIs should not be allowed simply because the token exists. Check signatures, expiration dates, issuers, purpose of use, account status, roles, and target lines in a consistent order. Refusals are also subject to audit, but you must not log the tokens themselves or passwords.

Approach to Analysis and Modeling

As a multi-layered defense, it determines (1) the form of credentials, (2) cryptographic verification, (3) claims, (4) account status, (5) roles, and (6) data range. Measuring the number of rejections per order of judgment makes it easier to distinguish between attack signs and configuration flaws. In HTTP, 401 unauthenticated is treated as a 403 if authenticated but insufficient permission is treated.

Check with Python

api_access["decision_reason"] = np.select(
    [
        ~api_access["token_present"],
        ~api_access["signature_valid"],
        api_access["token_expired"],
        ~api_access["account_status"].eq("active"),
        ~api_access["role_allowed"],
        ~api_access["scope_allowed"],
    ],
    ["tokenNone", "improper signature", "expired", "Account Invalidation", "Roll shortage", "outside the scope of responsibility"],
    default="permission",
)
decision_summary = api_access["decision_reason"].value_counts().rename_axis("Judgment").reset_index(name="number_of_cases")
decision_summary["composition_ratio_%"] = (decision_summary["number_of_cases"] / len(api_access) * 100).round(1)
display(decision_summary)

fig, ax = plt.subplots(figsize=(8.5, 4.2))
colors = ["#2A9D8F" if x == "permission" else "#E76F51" for x in decision_summary["Judgment"]]
ax.bar(decision_summary["Judgment"], decision_summary["number_of_cases"], color=colors)
ax.set_title("With authenticationAPIFinal Judgment and Reasons for Rejection")
ax.set_xlabel("Reasoning for Determination")
ax.set_ylabel("Number of Required Items")
ax.grid(axis="y", alpha=0.3)
plt.xticks(rotation=20)
plt.tight_layout()
plt.show()
Judgment number_of_cases composition_ratio_%
0 permission 677 28.2
1 outside the scope of responsibility 648 27.0
2 Roll shortage 578 24.1
3 Account Invalidation 327 13.6
4 expired 92 3.8
5 tokenNone 59 2.5
6 improper signature 19 0.8

svg

Reading the results

Depending on the number of rejection reasons, you can distinguish whether the deadline is too short, whether the privilege list does not fit the work, or whether signature fraud is increasing. However, a low rejection rate does not necessarily mean safety. Automatically test for any endpoints with protection loopholes, and consider audit logs for reauthentication, approval, and tamper-resistant for privileged operations.

Practical Implications Seen Through Target Exercise

  1. Successful authentication does not mean operation authorization
    After identity verification, you need to determine your role and scope of responsibility for each request.

  2. The front end is the wiring,APIis a mandatory point.
    Menu display control is effective for ease of use, but security boundaries are placed on the API side.

  3. On shared devices, session design directly impacts business quality.
    It integrates user name display, no-operation period, logout during rotation, and rapid re-authentication.

  4. Delegate authority to duties rather than individuals, and conduct regular inventory.
    Combine RBAC with affiliation scope to reflect deadlines for transfers, resignations, and support work.

  5. Treating rejection as a management metric rather than an abnormal termination
    By separating authentication failures, missing roles, out-of-responsibility, and expired roles, you can detect signs of attack and inconsistencies in business design.

What is necessary for practical implementation

1. Organizing Operations and the ID Lifecycle

Define who can access which system and for how long at the time of joining, transferring, support work, leave, or retirement. Assign responsible persons for coordination with HR and organizational masters, applications and approvals, emergency access, and regular inventory.

2. Selection of Threat Models and Authentication Methods

Based on shared terminals, factory networks, external access, and the importance of quality information handled, select SSO, MFA, passkeys, terminal certificates, and session deadlines. We do not decide based solely on the method name; instead, we assume device loss, phishing, internal fraud, and communication interruptions.

3. Centralized authorization and automated testing

To prevent permission definitions from becoming fragmented across screens, APIs, and batches, common policies and auditable change procedures are established. Include unauthenticated, expired, missing roles, out-of-control, and immediately after permission changes in the test cases.

4. Monitoring and Incident Response

Monitor for consecutive failures, abnormal devices and time slots, privileged manipulations, and sudden increases in denials. No confidential information is left in the logs, and retention periods, viewing permissions, time synchronization, and reporting and containment procedures are specified.

5. On-site usability verification

In real-world environments including gloves, noise, number of devices, shift times, and communication quality, login completion time, reauthentication count, work interruptions, and inquiries are measured to update the balance with safety.

Conclusion

From No.051 to No.060, everything from separation of authentication and authorization to login, password, JWT, frontend status, logout, RBAC, screen switching, and API protection was checked as a factory work performance and quality record system.

What matters is not the introduction of JWT or login screens themselves, but the It is possible to consistently verify the individual, their duties, scope of scope, and valid time, and audit their judgments.. As seen in the aggregated fictitious logs, tracking not only the number of permits but also the reasons for denial, device-specific completion times, and remaining sessions provides materials to improve both security and business continuity.

For actual implementation, design according to existing ID infrastructure, division of duties, shared device operation, and legal and business partner requirements, and continue regular permission reviews and testing.

Consultations for Corporations

At Suri Kobo, we support the design and development of web systems and certification approval platforms to safely operate these processes in manufacturing, including business organization, data analysis, and AI and mathematical model development.

  • We want to design login sessions based on shared terminals in factories.
  • I want to organize authority at the department, factory, or line level.
  • Want to incorporate authentication and authorization into analytics dashboards and AI APIs
  • Want to check for permission leaks and audit logs in existing systems
  • I want to organize the security requirements needed to move from PoC to production.

📩 Contact Us: surikobo.co.jp/contact
Please feel free to consult us first.