diff --git a/src/api/authenticate.ts b/src/api/authenticate.ts
index b289959ac..537c3d1e1 100644
--- a/src/api/authenticate.ts
+++ b/src/api/authenticate.ts
@@ -34,7 +34,7 @@ export default (req: express.Request) => new Promise<IAuthContext>(async (resolv
 
 	if (isNativeToken(token)) {
 		const user: IUser = await User
-			.findOne({ token: token });
+			.findOne({ 'account.token': token });
 
 		if (user === null) {
 			return reject('user not found');
diff --git a/src/api/bot/core.ts b/src/api/bot/core.ts
index 1f07d4eee..ad29f1003 100644
--- a/src/api/bot/core.ts
+++ b/src/api/bot/core.ts
@@ -225,7 +225,7 @@ class SigninContext extends Context {
 			}
 		} else {
 			// Compare password
-			const same = await bcrypt.compare(query, this.temporaryUser.password);
+			const same = await bcrypt.compare(query, this.temporaryUser.account.password);
 
 			if (same) {
 				this.bot.signin(this.temporaryUser);
diff --git a/src/api/bot/interfaces/line.ts b/src/api/bot/interfaces/line.ts
index 43c25f803..bf0882159 100644
--- a/src/api/bot/interfaces/line.ts
+++ b/src/api/bot/interfaces/line.ts
@@ -110,11 +110,11 @@ class LineBot extends BotCore {
 			data: `showtl|${user.id}`
 		});
 
-		if (user.twitter) {
+		if (user.account.twitter) {
 			actions.push({
 				type: 'uri',
 				label: 'Twitterアカウントを見る',
-				uri: `https://twitter.com/${user.twitter.screen_name}`
+				uri: `https://twitter.com/${user.account.twitter.screen_name}`
 			});
 		}
 
@@ -171,7 +171,7 @@ module.exports = async (app: express.Application) => {
 
 		if (session == null) {
 			const user = await User.findOne({
-				line: {
+				'account.line': {
 					user_id: sourceId
 				}
 			});
@@ -181,7 +181,7 @@ module.exports = async (app: express.Application) => {
 			bot.on('signin', user => {
 				User.update(user._id, {
 					$set: {
-						line: {
+						'account.line': {
 							user_id: sourceId
 						}
 					}
@@ -191,7 +191,7 @@ module.exports = async (app: express.Application) => {
 			bot.on('signout', user => {
 				User.update(user._id, {
 					$set: {
-						line: {
+						'account.line': {
 							user_id: null
 						}
 					}
diff --git a/src/api/common/signin.ts b/src/api/common/signin.ts
index ec3dd8030..04c2cdac8 100644
--- a/src/api/common/signin.ts
+++ b/src/api/common/signin.ts
@@ -2,7 +2,7 @@ import config from '../../conf';
 
 export default function(res, user, redirect: boolean) {
 	const expires = 1000 * 60 * 60 * 24 * 365; // One Year
-	res.cookie('i', user.token, {
+	res.cookie('i', user.account.token, {
 		path: '/',
 		domain: `.${config.hostname}`,
 		secure: config.url.substr(0, 5) === 'https',
diff --git a/src/api/endpoints/auth/accept.ts b/src/api/endpoints/auth/accept.ts
index 4ee20a6d2..8955738eb 100644
--- a/src/api/endpoints/auth/accept.ts
+++ b/src/api/endpoints/auth/accept.ts
@@ -45,7 +45,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 
 	// Fetch token
 	const session = await AuthSess
-		.findOne({ token: token });
+		.findOne({ 'account.token': token });
 
 	if (session === null) {
 		return rej('session not found');
diff --git a/src/api/endpoints/following/create.ts b/src/api/endpoints/following/create.ts
index 8e1aa3471..767b837b3 100644
--- a/src/api/endpoints/following/create.ts
+++ b/src/api/endpoints/following/create.ts
@@ -32,7 +32,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}, {
 		fields: {
 			data: false,
-			profile: false
+			'account.profile': false
 		}
 	});
 
diff --git a/src/api/endpoints/following/delete.ts b/src/api/endpoints/following/delete.ts
index b68cec09d..64b9a8cec 100644
--- a/src/api/endpoints/following/delete.ts
+++ b/src/api/endpoints/following/delete.ts
@@ -31,7 +31,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}, {
 		fields: {
 			data: false,
-			profile: false
+			'account.profile': false
 		}
 	});
 
diff --git a/src/api/endpoints/i.ts b/src/api/endpoints/i.ts
index 7efdbcd7c..32b0382fa 100644
--- a/src/api/endpoints/i.ts
+++ b/src/api/endpoints/i.ts
@@ -22,7 +22,7 @@ module.exports = (params, user, _, isSecure) => new Promise(async (res, rej) =>
 	// Update lastUsedAt
 	User.update({ _id: user._id }, {
 		$set: {
-			last_used_at: new Date()
+			'account.last_used_at': new Date()
 		}
 	});
 });
diff --git a/src/api/endpoints/i/2fa/done.ts b/src/api/endpoints/i/2fa/done.ts
index 0b36033bb..0f1db7382 100644
--- a/src/api/endpoints/i/2fa/done.ts
+++ b/src/api/endpoints/i/2fa/done.ts
@@ -28,8 +28,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	await User.update(user._id, {
 		$set: {
-			two_factor_secret: user.two_factor_temp_secret,
-			two_factor_enabled: true
+			'account.two_factor_secret': user.two_factor_temp_secret,
+			'account.two_factor_enabled': true
 		}
 	});
 
diff --git a/src/api/endpoints/i/2fa/register.ts b/src/api/endpoints/i/2fa/register.ts
index c2b5037a2..24abfcdfc 100644
--- a/src/api/endpoints/i/2fa/register.ts
+++ b/src/api/endpoints/i/2fa/register.ts
@@ -14,7 +14,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (passwordErr) return rej('invalid password param');
 
 	// Compare password
-	const same = await bcrypt.compare(password, user.password);
+	const same = await bcrypt.compare(password, user.account.password);
 
 	if (!same) {
 		return rej('incorrect password');
diff --git a/src/api/endpoints/i/2fa/unregister.ts b/src/api/endpoints/i/2fa/unregister.ts
index 6bee6a26f..c43f9ccc4 100644
--- a/src/api/endpoints/i/2fa/unregister.ts
+++ b/src/api/endpoints/i/2fa/unregister.ts
@@ -11,7 +11,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (passwordErr) return rej('invalid password param');
 
 	// Compare password
-	const same = await bcrypt.compare(password, user.password);
+	const same = await bcrypt.compare(password, user.account.password);
 
 	if (!same) {
 		return rej('incorrect password');
@@ -19,8 +19,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	await User.update(user._id, {
 		$set: {
-			two_factor_secret: null,
-			two_factor_enabled: false
+			'account.two_factor_secret': null,
+			'account.two_factor_enabled': false
 		}
 	});
 
diff --git a/src/api/endpoints/i/change_password.ts b/src/api/endpoints/i/change_password.ts
index 16f1a2e4e..88fb36b1f 100644
--- a/src/api/endpoints/i/change_password.ts
+++ b/src/api/endpoints/i/change_password.ts
@@ -22,7 +22,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (newPasswordErr) return rej('invalid new_password param');
 
 	// Compare password
-	const same = await bcrypt.compare(currentPassword, user.password);
+	const same = await bcrypt.compare(currentPassword, user.account.password);
 
 	if (!same) {
 		return rej('incorrect password');
@@ -34,7 +34,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	await User.update(user._id, {
 		$set: {
-			password: hash
+			'account.password': hash
 		}
 	});
 
diff --git a/src/api/endpoints/i/regenerate_token.ts b/src/api/endpoints/i/regenerate_token.ts
index 653468330..9ac7b5507 100644
--- a/src/api/endpoints/i/regenerate_token.ts
+++ b/src/api/endpoints/i/regenerate_token.ts
@@ -20,7 +20,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (passwordErr) return rej('invalid password param');
 
 	// Compare password
-	const same = await bcrypt.compare(password, user.password);
+	const same = await bcrypt.compare(password, user.account.password);
 
 	if (!same) {
 		return rej('incorrect password');
@@ -31,7 +31,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 	await User.update(user._id, {
 		$set: {
-			token: secret
+			'account.token': secret
 		}
 	});
 
diff --git a/src/api/endpoints/i/update.ts b/src/api/endpoints/i/update.ts
index 76bad2d15..db8a3f25b 100644
--- a/src/api/endpoints/i/update.ts
+++ b/src/api/endpoints/i/update.ts
@@ -29,12 +29,12 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re
 	// Get 'location' parameter
 	const [location, locationErr] = $(params.location).optional.nullable.string().pipe(isValidLocation).$;
 	if (locationErr) return rej('invalid location param');
-	if (location !== undefined) user.profile.location = location;
+	if (location !== undefined) user.account.profile.location = location;
 
 	// Get 'birthday' parameter
 	const [birthday, birthdayErr] = $(params.birthday).optional.nullable.string().pipe(isValidBirthday).$;
 	if (birthdayErr) return rej('invalid birthday param');
-	if (birthday !== undefined) user.profile.birthday = birthday;
+	if (birthday !== undefined) user.account.profile.birthday = birthday;
 
 	// Get 'avatar_id' parameter
 	const [avatarId, avatarIdErr] = $(params.avatar_id).optional.id().$;
@@ -49,12 +49,12 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re
 	// Get 'is_bot' parameter
 	const [isBot, isBotErr] = $(params.is_bot).optional.boolean().$;
 	if (isBotErr) return rej('invalid is_bot param');
-	if (isBot != null) user.is_bot = isBot;
+	if (isBot != null) user.account.is_bot = isBot;
 
 	// Get 'auto_watch' parameter
 	const [autoWatch, autoWatchErr] = $(params.auto_watch).optional.boolean().$;
 	if (autoWatchErr) return rej('invalid auto_watch param');
-	if (autoWatch != null) user.settings.auto_watch = autoWatch;
+	if (autoWatch != null) user.account.settings.auto_watch = autoWatch;
 
 	await User.update(user._id, {
 		$set: {
@@ -62,9 +62,9 @@ module.exports = async (params, user, _, isSecure) => new Promise(async (res, re
 			description: user.description,
 			avatar_id: user.avatar_id,
 			banner_id: user.banner_id,
-			profile: user.profile,
-			is_bot: user.is_bot,
-			settings: user.settings
+			'account.profile': user.account.profile,
+			'account.is_bot': user.account.is_bot,
+			'account.settings': user.account.settings
 		}
 	});
 
diff --git a/src/api/endpoints/i/update_client_setting.ts b/src/api/endpoints/i/update_client_setting.ts
index b817ff354..c772ed5dc 100644
--- a/src/api/endpoints/i/update_client_setting.ts
+++ b/src/api/endpoints/i/update_client_setting.ts
@@ -22,14 +22,14 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (valueErr) return rej('invalid value param');
 
 	const x = {};
-	x[`client_settings.${name}`] = value;
+	x[`account.client_settings.${name}`] = value;
 
 	await User.update(user._id, {
 		$set: x
 	});
 
 	// Serialize
-	user.client_settings[name] = value;
+	user.account.client_settings[name] = value;
 	const iObj = await pack(user, user, {
 		detail: true,
 		includeSecrets: true
diff --git a/src/api/endpoints/i/update_home.ts b/src/api/endpoints/i/update_home.ts
index 394686cbd..9ce44e25e 100644
--- a/src/api/endpoints/i/update_home.ts
+++ b/src/api/endpoints/i/update_home.ts
@@ -26,7 +26,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (home) {
 		await User.update(user._id, {
 			$set: {
-				'client_settings.home': home
+				'account.client_settings.home': home
 			}
 		});
 
@@ -38,7 +38,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	} else {
 		if (id == null && data == null) return rej('you need to set id and data params if home param unset');
 
-		const _home = user.client_settings.home;
+		const _home = user.account.client_settings.home;
 		const widget = _home.find(w => w.id == id);
 
 		if (widget == null) return rej('widget not found');
@@ -47,7 +47,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 		await User.update(user._id, {
 			$set: {
-				'client_settings.home': _home
+				'account.client_settings.home': _home
 			}
 		});
 
diff --git a/src/api/endpoints/i/update_mobile_home.ts b/src/api/endpoints/i/update_mobile_home.ts
index 70181431a..1daddf42b 100644
--- a/src/api/endpoints/i/update_mobile_home.ts
+++ b/src/api/endpoints/i/update_mobile_home.ts
@@ -25,7 +25,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	if (home) {
 		await User.update(user._id, {
 			$set: {
-				'client_settings.mobile_home': home
+				'account.client_settings.mobile_home': home
 			}
 		});
 
@@ -37,7 +37,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 	} else {
 		if (id == null && data == null) return rej('you need to set id and data params if home param unset');
 
-		const _home = user.client_settings.mobile_home || [];
+		const _home = user.account.client_settings.mobile_home || [];
 		const widget = _home.find(w => w.id == id);
 
 		if (widget == null) return rej('widget not found');
@@ -46,7 +46,7 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
 
 		await User.update(user._id, {
 			$set: {
-				'client_settings.mobile_home': _home
+				'account.client_settings.mobile_home': _home
 			}
 		});
 
diff --git a/src/api/endpoints/mute/create.ts b/src/api/endpoints/mute/create.ts
index f44854ab5..f99b40d32 100644
--- a/src/api/endpoints/mute/create.ts
+++ b/src/api/endpoints/mute/create.ts
@@ -30,7 +30,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}, {
 		fields: {
 			data: false,
-			profile: false
+			'account.profile': false
 		}
 	});
 
diff --git a/src/api/endpoints/mute/delete.ts b/src/api/endpoints/mute/delete.ts
index d6bff3353..36e2fd101 100644
--- a/src/api/endpoints/mute/delete.ts
+++ b/src/api/endpoints/mute/delete.ts
@@ -30,7 +30,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 	}, {
 		fields: {
 			data: false,
-			profile: false
+			'account.profile': false
 		}
 	});
 
diff --git a/src/api/endpoints/posts/categorize.ts b/src/api/endpoints/posts/categorize.ts
index 3530ba6bc..0c85c2b4e 100644
--- a/src/api/endpoints/posts/categorize.ts
+++ b/src/api/endpoints/posts/categorize.ts
@@ -12,7 +12,7 @@ import Post from '../../models/post';
  * @return {Promise<any>}
  */
 module.exports = (params, user) => new Promise(async (res, rej) => {
-	if (!user.is_pro) {
+	if (!user.account.is_pro) {
 		return rej('This endpoint is available only from a Pro account');
 	}
 
diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts
index 1c3ab5345..f46a84e1f 100644
--- a/src/api/endpoints/posts/create.ts
+++ b/src/api/endpoints/posts/create.ts
@@ -390,7 +390,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => {
 			});
 
 		// この投稿をWatchする
-		if (user.settings.auto_watch !== false) {
+		if (user.account.settings.auto_watch !== false) {
 			watch(user._id, reply);
 		}
 
diff --git a/src/api/endpoints/posts/polls/vote.ts b/src/api/endpoints/posts/polls/vote.ts
index 8222fe532..16ce76a6f 100644
--- a/src/api/endpoints/posts/polls/vote.ts
+++ b/src/api/endpoints/posts/polls/vote.ts
@@ -100,7 +100,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		});
 
 	// この投稿をWatchする
-	if (user.settings.auto_watch !== false) {
+	if (user.account.settings.auto_watch !== false) {
 		watch(user._id, post);
 	}
 });
diff --git a/src/api/endpoints/posts/reactions/create.ts b/src/api/endpoints/posts/reactions/create.ts
index 93d9756d0..f77afed40 100644
--- a/src/api/endpoints/posts/reactions/create.ts
+++ b/src/api/endpoints/posts/reactions/create.ts
@@ -116,7 +116,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 		});
 
 	// この投稿をWatchする
-	if (user.settings.auto_watch !== false) {
+	if (user.account.settings.auto_watch !== false) {
 		watch(user._id, post);
 	}
 });
diff --git a/src/api/endpoints/users/recommendation.ts b/src/api/endpoints/users/recommendation.ts
index 736233b34..f1f5bcd0a 100644
--- a/src/api/endpoints/users/recommendation.ts
+++ b/src/api/endpoints/users/recommendation.ts
@@ -30,7 +30,7 @@ module.exports = (params, me) => new Promise(async (res, rej) => {
 			_id: {
 				$nin: followingIds
 			},
-			last_used_at: {
+			'account.last_used_at': {
 				$gte: new Date(Date.now() - ms('7days'))
 			}
 		}, {
diff --git a/src/api/models/user.ts b/src/api/models/user.ts
index ba2765c79..372e2c5da 100644
--- a/src/api/models/user.ts
+++ b/src/api/models/user.ts
@@ -11,7 +11,7 @@ import config from '../../conf';
 const User = db.get<IUser>('users');
 
 User.createIndex('username');
-User.createIndex('token');
+User.createIndex('account.token');
 
 export default User;
 
@@ -43,46 +43,48 @@ export type IUser = {
 	_id: mongo.ObjectID;
 	created_at: Date;
 	deleted_at: Date;
-	email: string;
 	followers_count: number;
 	following_count: number;
-	links: string[];
 	name: string;
-	password: string;
 	posts_count: number;
 	drive_capacity: number;
 	username: string;
 	username_lower: string;
-	token: string;
 	avatar_id: mongo.ObjectID;
 	banner_id: mongo.ObjectID;
 	data: any;
-	twitter: {
-		access_token: string;
-		access_token_secret: string;
-		user_id: string;
-		screen_name: string;
-	};
-	line: {
-		user_id: string;
-	};
 	description: string;
-	profile: {
-		location: string;
-		birthday: string; // 'YYYY-MM-DD'
-		tags: string[];
-	};
-	last_used_at: Date;
 	latest_post: IPost;
 	pinned_post_id: mongo.ObjectID;
-	is_bot: boolean;
-	is_pro: boolean;
 	is_suspended: boolean;
 	keywords: string[];
-	two_factor_secret: string;
-	two_factor_enabled: boolean;
-	client_settings: any;
-	settings: any;
+	account: {
+		email: string;
+		links: string[];
+		password: string;
+		token: string;
+		twitter: {
+			access_token: string;
+			access_token_secret: string;
+			user_id: string;
+			screen_name: string;
+		};
+		line: {
+			user_id: string;
+		};
+		profile: {
+			location: string;
+			birthday: string; // 'YYYY-MM-DD'
+			tags: string[];
+		};
+		last_used_at: Date;
+		is_bot: boolean;
+		is_pro: boolean;
+		two_factor_secret: string;
+		two_factor_enabled: boolean;
+		client_settings: any;
+		settings: any;
+	};
 };
 
 export function init(user): IUser {
@@ -119,11 +121,11 @@ export const pack = (
 
 	const fields = opts.detail ? {
 	} : {
-		settings: false,
-		client_settings: false,
-		profile: false,
-		keywords: false,
-		domains: false
+		'account.settings': false,
+		'account.client_settings': false,
+		'account.profile': false,
+		'account.keywords': false,
+		'account.domains': false
 	};
 
 	// Populate the user if 'user' is ID
@@ -158,26 +160,26 @@ export const pack = (
 	delete _user.latest_post;
 
 	// Remove private properties
-	delete _user.password;
-	delete _user.token;
-	delete _user.two_factor_temp_secret;
-	delete _user.two_factor_secret;
+	delete _user.account.password;
+	delete _user.account.token;
+	delete _user.account.two_factor_temp_secret;
+	delete _user.account.two_factor_secret;
 	delete _user.username_lower;
-	if (_user.twitter) {
-		delete _user.twitter.access_token;
-		delete _user.twitter.access_token_secret;
+	if (_user.account.twitter) {
+		delete _user.account.twitter.access_token;
+		delete _user.account.twitter.access_token_secret;
 	}
-	delete _user.line;
+	delete _user.account.line;
 
 	// Visible via only the official client
 	if (!opts.includeSecrets) {
-		delete _user.email;
-		delete _user.settings;
-		delete _user.client_settings;
+		delete _user.account.email;
+		delete _user.account.settings;
+		delete _user.account.client_settings;
 	}
 
 	if (!opts.detail) {
-		delete _user.two_factor_enabled;
+		delete _user.account.two_factor_enabled;
 	}
 
 	_user.avatar_url = _user.avatar_id != null
diff --git a/src/api/private/signin.ts b/src/api/private/signin.ts
index b49d25d99..ae0be03c7 100644
--- a/src/api/private/signin.ts
+++ b/src/api/private/signin.ts
@@ -36,7 +36,7 @@ export default async (req: express.Request, res: express.Response) => {
 	}, {
 		fields: {
 			data: false,
-			profile: false
+			'account.profile': false
 		}
 	});
 
@@ -48,12 +48,12 @@ export default async (req: express.Request, res: express.Response) => {
 	}
 
 	// Compare password
-	const same = await bcrypt.compare(password, user.password);
+	const same = await bcrypt.compare(password, user.account.password);
 
 	if (same) {
-		if (user.two_factor_enabled) {
+		if (user.account.two_factor_enabled) {
 			const verified = (speakeasy as any).totp.verify({
-				secret: user.two_factor_secret,
+				secret: user.account.two_factor_secret,
 				encoding: 'base32',
 				token: token
 			});
diff --git a/src/api/private/signup.ts b/src/api/private/signup.ts
index 3df00ae42..902642425 100644
--- a/src/api/private/signup.ts
+++ b/src/api/private/signup.ts
@@ -105,38 +105,40 @@ export default async (req: express.Request, res: express.Response) => {
 
 	// Create account
 	const account: IUser = await User.insert({
-		token: secret,
 		avatar_id: null,
 		banner_id: null,
 		created_at: new Date(),
 		description: null,
-		email: null,
 		followers_count: 0,
 		following_count: 0,
-		links: null,
 		name: name,
-		password: hash,
 		posts_count: 0,
 		likes_count: 0,
 		liked_count: 0,
 		drive_capacity: 1073741824, // 1GB
 		username: username,
 		username_lower: username.toLowerCase(),
-		profile: {
-			bio: null,
-			birthday: null,
-			blood: null,
-			gender: null,
-			handedness: null,
-			height: null,
-			location: null,
-			weight: null
-		},
-		settings: {
-			auto_watch: true
-		},
-		client_settings: {
-			home: homeData
+		account: {
+			token: secret,
+			email: null,
+			links: null,
+			password: hash,
+			profile: {
+				bio: null,
+				birthday: null,
+				blood: null,
+				gender: null,
+				handedness: null,
+				height: null,
+				location: null,
+				weight: null
+			},
+			settings: {
+				auto_watch: true
+			},
+			client_settings: {
+				home: homeData
+			}
 		}
 	});
 
diff --git a/src/api/service/twitter.ts b/src/api/service/twitter.ts
index adcd5ac49..02b613454 100644
--- a/src/api/service/twitter.ts
+++ b/src/api/service/twitter.ts
@@ -39,10 +39,10 @@ module.exports = (app: express.Application) => {
 		if (userToken == null) return res.send('plz signin');
 
 		const user = await User.findOneAndUpdate({
-			token: userToken
+			'account.token': userToken
 		}, {
 			$set: {
-				twitter: null
+				'account.twitter': null
 			}
 		});
 
@@ -126,7 +126,7 @@ module.exports = (app: express.Application) => {
 				const result = await twAuth.done(JSON.parse(ctx), req.query.oauth_verifier);
 
 				const user = await User.findOne({
-					'twitter.user_id': result.userId
+					'account.twitter.user_id': result.userId
 				});
 
 				if (user == null) {
@@ -148,10 +148,10 @@ module.exports = (app: express.Application) => {
 				const result = await twAuth.done(JSON.parse(ctx), verifier);
 
 				const user = await User.findOneAndUpdate({
-					token: userToken
+					'account.token': userToken
 				}, {
 					$set: {
-						twitter: {
+						'account.twitter': {
 							access_token: result.accessToken,
 							access_token_secret: result.accessTokenSecret,
 							user_id: result.userId,
diff --git a/src/api/stream/home.ts b/src/api/stream/home.ts
index cc3fb885e..1ef0f33b4 100644
--- a/src/api/stream/home.ts
+++ b/src/api/stream/home.ts
@@ -74,7 +74,7 @@ export default async function(request: websocket.request, connection: websocket.
 				// Update lastUsedAt
 				User.update({ _id: user._id }, {
 					$set: {
-						last_used_at: new Date()
+						'account.last_used_at': new Date()
 					}
 				});
 				break;
diff --git a/src/api/streaming.ts b/src/api/streaming.ts
index f56c08092..427e01afd 100644
--- a/src/api/streaming.ts
+++ b/src/api/streaming.ts
@@ -94,7 +94,7 @@ function authenticate(token: string): Promise<IUser> {
 			// Fetch user
 			const user: IUser = await User
 				.findOne({
-					token: token
+					'account.token': token
 				});
 
 			resolve(user);
diff --git a/src/common/get-user-summary.ts b/src/common/get-user-summary.ts
index 1bec2f9a2..619814e8a 100644
--- a/src/common/get-user-summary.ts
+++ b/src/common/get-user-summary.ts
@@ -7,6 +7,6 @@ import { IUser } from '../api/models/user';
 export default function(user: IUser): string {
 	return `${user.name} (@${user.username})\n` +
 		`${user.posts_count}投稿、${user.following_count}フォロー、${user.followers_count}フォロワー\n` +
-		`場所: ${user.profile.location}、誕生日: ${user.profile.birthday}\n` +
+		`場所: ${user.account.profile.location}、誕生日: ${user.account.profile.birthday}\n` +
 		`「${user.description}」`;
 }
diff --git a/src/web/app/common/define-widget.ts b/src/web/app/common/define-widget.ts
index efce7e813..d8d29873a 100644
--- a/src/web/app/common/define-widget.ts
+++ b/src/web/app/common/define-widget.ts
@@ -56,14 +56,14 @@ export default function<T extends object>(data: {
 						id: this.id,
 						data: newProps
 					}).then(() => {
-						(this as any).os.i.client_settings.mobile_home.find(w => w.id == this.id).data = newProps;
+						(this as any).os.i.account.client_settings.mobile_home.find(w => w.id == this.id).data = newProps;
 					});
 				} else {
 					(this as any).api('i/update_home', {
 						id: this.id,
 						data: newProps
 					}).then(() => {
-						(this as any).os.i.client_settings.home.find(w => w.id == this.id).data = newProps;
+						(this as any).os.i.account.client_settings.home.find(w => w.id == this.id).data = newProps;
 					});
 				}
 			}, {
diff --git a/src/web/app/common/mios.ts b/src/web/app/common/mios.ts
index 582a46c4c..2c6c9988e 100644
--- a/src/web/app/common/mios.ts
+++ b/src/web/app/common/mios.ts
@@ -270,7 +270,7 @@ export default class MiOS extends EventEmitter {
 				// Parse response
 				res.json().then(i => {
 					me = i;
-					me.token = token;
+					me.account.token = token;
 					done();
 				});
 			})
@@ -294,12 +294,12 @@ export default class MiOS extends EventEmitter {
 		const fetched = me => {
 			if (me) {
 				// デフォルトの設定をマージ
-				me.client_settings = Object.assign({
+				me.account.client_settings = Object.assign({
 					fetchOnScroll: true,
 					showMaps: true,
 					showPostFormOnTopOfTl: false,
 					gradientWindowHeader: false
-				}, me.client_settings);
+				}, me.account.client_settings);
 
 				// ローカルストレージにキャッシュ
 				localStorage.setItem('me', JSON.stringify(me));
@@ -329,7 +329,7 @@ export default class MiOS extends EventEmitter {
 			fetched(cachedMe);
 
 			// 後から新鮮なデータをフェッチ
-			fetchme(cachedMe.token, freshData => {
+			fetchme(cachedMe.account.token, freshData => {
 				merge(cachedMe, freshData);
 			});
 		} else {
@@ -437,7 +437,7 @@ export default class MiOS extends EventEmitter {
 		}
 
 		// Append a credential
-		if (this.isSignedIn) (data as any).i = this.i.token;
+		if (this.isSignedIn) (data as any).i = this.i.account.token;
 
 		// TODO
 		//const viaStream = localStorage.getItem('enableExperimental') == 'true';
diff --git a/src/web/app/common/scripts/streaming/drive.ts b/src/web/app/common/scripts/streaming/drive.ts
index 7ff85b594..f11573685 100644
--- a/src/web/app/common/scripts/streaming/drive.ts
+++ b/src/web/app/common/scripts/streaming/drive.ts
@@ -8,7 +8,7 @@ import MiOS from '../../mios';
 export class DriveStream extends Stream {
 	constructor(os: MiOS, me) {
 		super(os, 'drive', {
-			i: me.token
+			i: me.account.token
 		});
 	}
 }
diff --git a/src/web/app/common/scripts/streaming/home.ts b/src/web/app/common/scripts/streaming/home.ts
index 533c23244..ffcf6e536 100644
--- a/src/web/app/common/scripts/streaming/home.ts
+++ b/src/web/app/common/scripts/streaming/home.ts
@@ -10,13 +10,13 @@ import MiOS from '../../mios';
 export class HomeStream extends Stream {
 	constructor(os: MiOS, me) {
 		super(os, '', {
-			i: me.token
+			i: me.account.token
 		});
 
 		// 最終利用日時を更新するため定期的にaliveメッセージを送信
 		setInterval(() => {
 			this.send({ type: 'alive' });
-			me.last_used_at = new Date();
+			me.account.last_used_at = new Date();
 		}, 1000 * 60);
 
 		// 自分の情報が更新されたとき
diff --git a/src/web/app/common/scripts/streaming/messaging-index.ts b/src/web/app/common/scripts/streaming/messaging-index.ts
index 84e2174ec..24f0ce0c9 100644
--- a/src/web/app/common/scripts/streaming/messaging-index.ts
+++ b/src/web/app/common/scripts/streaming/messaging-index.ts
@@ -8,7 +8,7 @@ import MiOS from '../../mios';
 export class MessagingIndexStream extends Stream {
 	constructor(os: MiOS, me) {
 		super(os, 'messaging-index', {
-			i: me.token
+			i: me.account.token
 		});
 	}
 }
diff --git a/src/web/app/common/scripts/streaming/messaging.ts b/src/web/app/common/scripts/streaming/messaging.ts
index c1b5875cf..4c593deb3 100644
--- a/src/web/app/common/scripts/streaming/messaging.ts
+++ b/src/web/app/common/scripts/streaming/messaging.ts
@@ -7,13 +7,13 @@ import MiOS from '../../mios';
 export class MessagingStream extends Stream {
 	constructor(os: MiOS, me, otherparty) {
 		super(os, 'messaging', {
-			i: me.token,
+			i: me.account.token,
 			otherparty
 		});
 
 		(this as any).on('_connected_', () => {
 			this.send({
-				i: me.token
+				i: me.account.token
 			});
 		});
 	}
diff --git a/src/web/app/common/scripts/streaming/othello-game.ts b/src/web/app/common/scripts/streaming/othello-game.ts
index b85af8f72..f34ef3514 100644
--- a/src/web/app/common/scripts/streaming/othello-game.ts
+++ b/src/web/app/common/scripts/streaming/othello-game.ts
@@ -4,7 +4,7 @@ import MiOS from '../../mios';
 export class OthelloGameStream extends Stream {
 	constructor(os: MiOS, me, game) {
 		super(os, 'othello-game', {
-			i: me ? me.token : null,
+			i: me ? me.account.token : null,
 			game: game.id
 		});
 	}
diff --git a/src/web/app/common/scripts/streaming/othello.ts b/src/web/app/common/scripts/streaming/othello.ts
index f5d47431c..8c6f4b9c3 100644
--- a/src/web/app/common/scripts/streaming/othello.ts
+++ b/src/web/app/common/scripts/streaming/othello.ts
@@ -5,7 +5,7 @@ import MiOS from '../../mios';
 export class OthelloStream extends Stream {
 	constructor(os: MiOS, me) {
 		super(os, 'othello', {
-			i: me.token
+			i: me.account.token
 		});
 	}
 }
diff --git a/src/web/app/common/views/components/signin.vue b/src/web/app/common/views/components/signin.vue
index 1738d0df7..d8b135776 100644
--- a/src/web/app/common/views/components/signin.vue
+++ b/src/web/app/common/views/components/signin.vue
@@ -6,7 +6,7 @@
 	<label class="password">
 		<input v-model="password" type="password" placeholder="%i18n:common.tags.mk-signin.password%" required/>%fa:lock%
 	</label>
-	<label class="token" v-if="user && user.two_factor_enabled">
+	<label class="token" v-if="user && user.account.two_factor_enabled">
 		<input v-model="token" type="number" placeholder="%i18n:common.tags.mk-signin.token%" required/>%fa:lock%
 	</label>
 	<button type="submit" :disabled="signing">{{ signing ? '%i18n:common.tags.mk-signin.signing-in%' : '%i18n:common.tags.mk-signin.signin%' }}</button>
@@ -40,7 +40,7 @@ export default Vue.extend({
 			(this as any).api('signin', {
 				username: this.username,
 				password: this.password,
-				token: this.user && this.user.two_factor_enabled ? this.token : undefined
+				token: this.user && this.user.account.two_factor_enabled ? this.token : undefined
 			}).then(() => {
 				location.reload();
 			}).catch(() => {
diff --git a/src/web/app/common/views/components/twitter-setting.vue b/src/web/app/common/views/components/twitter-setting.vue
index a0de27085..15968d20a 100644
--- a/src/web/app/common/views/components/twitter-setting.vue
+++ b/src/web/app/common/views/components/twitter-setting.vue
@@ -1,13 +1,13 @@
 <template>
 <div class="mk-twitter-setting">
 	<p>%i18n:common.tags.mk-twitter-setting.description%<a :href="`${docsUrl}/link-to-twitter`" target="_blank">%i18n:common.tags.mk-twitter-setting.detail%</a></p>
-	<p class="account" v-if="os.i.twitter" :title="`Twitter ID: ${os.i.twitter.user_id}`">%i18n:common.tags.mk-twitter-setting.connected-to%: <a :href="`https://twitter.com/${os.i.twitter.screen_name}`" target="_blank">@{{ os.i.twitter.screen_name }}</a></p>
+	<p class="account" v-if="os.i.account.twitter" :title="`Twitter ID: ${os.i.account.twitter.user_id}`">%i18n:common.tags.mk-twitter-setting.connected-to%: <a :href="`https://twitter.com/${os.i.account.twitter.screen_name}`" target="_blank">@{{ os.i.account.twitter.screen_name }}</a></p>
 	<p>
-		<a :href="`${apiUrl}/connect/twitter`" target="_blank" @click.prevent="connect">{{ os.i.twitter ? '%i18n:common.tags.mk-twitter-setting.reconnect%' : '%i18n:common.tags.mk-twitter-setting.connect%' }}</a>
-		<span v-if="os.i.twitter"> or </span>
-		<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.twitter" @click.prevent="disconnect">%i18n:common.tags.mk-twitter-setting.disconnect%</a>
+		<a :href="`${apiUrl}/connect/twitter`" target="_blank" @click.prevent="connect">{{ os.i.account.twitter ? '%i18n:common.tags.mk-twitter-setting.reconnect%' : '%i18n:common.tags.mk-twitter-setting.connect%' }}</a>
+		<span v-if="os.i.account.twitter"> or </span>
+		<a :href="`${apiUrl}/disconnect/twitter`" target="_blank" v-if="os.i.account.twitter" @click.prevent="disconnect">%i18n:common.tags.mk-twitter-setting.disconnect%</a>
 	</p>
-	<p class="id" v-if="os.i.twitter">Twitter ID: {{ os.i.twitter.user_id }}</p>
+	<p class="id" v-if="os.i.account.twitter">Twitter ID: {{ os.i.account.twitter.user_id }}</p>
 </div>
 </template>
 
@@ -25,7 +25,7 @@ export default Vue.extend({
 	},
 	mounted() {
 		this.$watch('os.i', () => {
-			if ((this as any).os.i.twitter) {
+			if ((this as any).os.i.account.twitter) {
 				if (this.form) this.form.close();
 			}
 		}, {
diff --git a/src/web/app/common/views/components/uploader.vue b/src/web/app/common/views/components/uploader.vue
index 6465ad35e..73006b16e 100644
--- a/src/web/app/common/views/components/uploader.vue
+++ b/src/web/app/common/views/components/uploader.vue
@@ -50,7 +50,7 @@ export default Vue.extend({
 			reader.readAsDataURL(file);
 
 			const data = new FormData();
-			data.append('i', (this as any).os.i.token);
+			data.append('i', (this as any).os.i.account.token);
 			data.append('file', file);
 
 			if (folder) data.append('folder_id', folder);
diff --git a/src/web/app/desktop/api/update-avatar.ts b/src/web/app/desktop/api/update-avatar.ts
index c3e0ce14c..8f748d853 100644
--- a/src/web/app/desktop/api/update-avatar.ts
+++ b/src/web/app/desktop/api/update-avatar.ts
@@ -16,7 +16,7 @@ export default (os: OS) => (cb, file = null) => {
 
 		w.$once('cropped', blob => {
 			const data = new FormData();
-			data.append('i', os.i.token);
+			data.append('i', os.i.account.token);
 			data.append('file', blob, file.name + '.cropped.png');
 
 			os.api('drive/folders/find', {
diff --git a/src/web/app/desktop/api/update-banner.ts b/src/web/app/desktop/api/update-banner.ts
index 9e94dc423..9ed48b267 100644
--- a/src/web/app/desktop/api/update-banner.ts
+++ b/src/web/app/desktop/api/update-banner.ts
@@ -16,7 +16,7 @@ export default (os: OS) => (cb, file = null) => {
 
 		w.$once('cropped', blob => {
 			const data = new FormData();
-			data.append('i', os.i.token);
+			data.append('i', os.i.account.token);
 			data.append('file', blob, file.name + '.cropped.png');
 
 			os.api('drive/folders/find', {
diff --git a/src/web/app/desktop/views/components/home.vue b/src/web/app/desktop/views/components/home.vue
index 562b22d11..a4ce1ef94 100644
--- a/src/web/app/desktop/views/components/home.vue
+++ b/src/web/app/desktop/views/components/home.vue
@@ -53,7 +53,7 @@
 			<div class="main">
 				<a @click="hint">カスタマイズのヒント</a>
 				<div>
-					<mk-post-form v-if="os.i.client_settings.showPostFormOnTopOfTl"/>
+					<mk-post-form v-if="os.i.account.client_settings.showPostFormOnTopOfTl"/>
 					<mk-timeline ref="tl" @loaded="onTlLoaded"/>
 				</div>
 			</div>
@@ -63,7 +63,7 @@
 				<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp"/>
 			</div>
 			<div class="main">
-				<mk-post-form v-if="os.i.client_settings.showPostFormOnTopOfTl"/>
+				<mk-post-form v-if="os.i.account.client_settings.showPostFormOnTopOfTl"/>
 				<mk-timeline ref="tl" @loaded="onTlLoaded" v-if="mode == 'timeline'"/>
 				<mk-mentions @loaded="onTlLoaded" v-if="mode == 'mentions'"/>
 			</div>
@@ -104,16 +104,16 @@ export default Vue.extend({
 		home: {
 			get(): any[] {
 				//#region 互換性のため
-				(this as any).os.i.client_settings.home.forEach(w => {
+				(this as any).os.i.account.client_settings.home.forEach(w => {
 					if (w.name == 'rss-reader') w.name = 'rss';
 					if (w.name == 'user-recommendation') w.name = 'users';
 					if (w.name == 'recommended-polls') w.name = 'polls';
 				});
 				//#endregion
-				return (this as any).os.i.client_settings.home;
+				return (this as any).os.i.account.client_settings.home;
 			},
 			set(value) {
-				(this as any).os.i.client_settings.home = value;
+				(this as any).os.i.account.client_settings.home = value;
 			}
 		},
 		left(): any[] {
@@ -126,7 +126,7 @@ export default Vue.extend({
 	created() {
 		this.widgets.left = this.left;
 		this.widgets.right = this.right;
-		this.$watch('os.i.client_settings', i => {
+		this.$watch('os.i.account.client_settings', i => {
 			this.widgets.left = this.left;
 			this.widgets.right = this.right;
 		}, {
@@ -161,17 +161,17 @@ export default Vue.extend({
 		},
 		onHomeUpdated(data) {
 			if (data.home) {
-				(this as any).os.i.client_settings.home = data.home;
+				(this as any).os.i.account.client_settings.home = data.home;
 				this.widgets.left = data.home.filter(w => w.place == 'left');
 				this.widgets.right = data.home.filter(w => w.place == 'right');
 			} else {
-				const w = (this as any).os.i.client_settings.home.find(w => w.id == data.id);
+				const w = (this as any).os.i.account.client_settings.home.find(w => w.id == data.id);
 				if (w != null) {
 					w.data = data.data;
 					this.$refs[w.id][0].preventSave = true;
 					this.$refs[w.id][0].props = w.data;
-					this.widgets.left = (this as any).os.i.client_settings.home.filter(w => w.place == 'left');
-					this.widgets.right = (this as any).os.i.client_settings.home.filter(w => w.place == 'right');
+					this.widgets.left = (this as any).os.i.account.client_settings.home.filter(w => w.place == 'left');
+					this.widgets.right = (this as any).os.i.account.client_settings.home.filter(w => w.place == 'right');
 				}
 			}
 		},
diff --git a/src/web/app/desktop/views/components/post-detail.vue b/src/web/app/desktop/views/components/post-detail.vue
index e454c2870..98777e224 100644
--- a/src/web/app/desktop/views/components/post-detail.vue
+++ b/src/web/app/desktop/views/components/post-detail.vue
@@ -148,7 +148,7 @@ export default Vue.extend({
 
 		// Draw map
 		if (this.p.geo) {
-			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.client_settings.showMaps : true;
+			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.client_settings.showMaps : true;
 			if (shouldShowMap) {
 				(this as any).os.getGoogleMaps().then(maps => {
 					const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude);
diff --git a/src/web/app/desktop/views/components/posts.post.vue b/src/web/app/desktop/views/components/posts.post.vue
index ddc338e37..073b89957 100644
--- a/src/web/app/desktop/views/components/posts.post.vue
+++ b/src/web/app/desktop/views/components/posts.post.vue
@@ -22,7 +22,7 @@
 		<div class="main">
 			<header>
 				<router-link class="name" :to="`/${p.user.username}`" v-user-preview="p.user.id">{{ p.user.name }}</router-link>
-				<span class="is-bot" v-if="p.user.is_bot">bot</span>
+				<span class="is-bot" v-if="p.user.account.is_bot">bot</span>
 				<span class="username">@{{ p.user.username }}</span>
 				<div class="info">
 					<span class="app" v-if="p.app">via <b>{{ p.app.name }}</b></span>
@@ -162,7 +162,7 @@ export default Vue.extend({
 
 		// Draw map
 		if (this.p.geo) {
-			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.client_settings.showMaps : true;
+			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.client_settings.showMaps : true;
 			if (shouldShowMap) {
 				(this as any).os.getGoogleMaps().then(maps => {
 					const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude);
diff --git a/src/web/app/desktop/views/components/settings.2fa.vue b/src/web/app/desktop/views/components/settings.2fa.vue
index 87783e799..85f2d6ba5 100644
--- a/src/web/app/desktop/views/components/settings.2fa.vue
+++ b/src/web/app/desktop/views/components/settings.2fa.vue
@@ -2,8 +2,8 @@
 <div class="2fa">
 	<p>%i18n:desktop.tags.mk-2fa-setting.intro%<a href="%i18n:desktop.tags.mk-2fa-setting.url%" target="_blank">%i18n:desktop.tags.mk-2fa-setting.detail%</a></p>
 	<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:desktop.tags.mk-2fa-setting.caution%</p></div>
-	<p v-if="!data && !os.i.two_factor_enabled"><button @click="register" class="ui primary">%i18n:desktop.tags.mk-2fa-setting.register%</button></p>
-	<template v-if="os.i.two_factor_enabled">
+	<p v-if="!data && !os.i.account.two_factor_enabled"><button @click="register" class="ui primary">%i18n:desktop.tags.mk-2fa-setting.register%</button></p>
+	<template v-if="os.i.account.two_factor_enabled">
 		<p>%i18n:desktop.tags.mk-2fa-setting.already-registered%</p>
 		<button @click="unregister" class="ui">%i18n:desktop.tags.mk-2fa-setting.unregister%</button>
 	</template>
@@ -54,7 +54,7 @@ export default Vue.extend({
 					password: password
 				}).then(() => {
 					(this as any).apis.notify('%i18n:desktop.tags.mk-2fa-setting.unregistered%');
-					(this as any).os.i.two_factor_enabled = false;
+					(this as any).os.i.account.two_factor_enabled = false;
 				});
 			});
 		},
@@ -64,7 +64,7 @@ export default Vue.extend({
 				token: this.token
 			}).then(() => {
 				(this as any).apis.notify('%i18n:desktop.tags.mk-2fa-setting.success%');
-				(this as any).os.i.two_factor_enabled = true;
+				(this as any).os.i.account.two_factor_enabled = true;
 			}).catch(() => {
 				(this as any).apis.notify('%i18n:desktop.tags.mk-2fa-setting.failed%');
 			});
diff --git a/src/web/app/desktop/views/components/settings.api.vue b/src/web/app/desktop/views/components/settings.api.vue
index 5831f8207..0d5921ab7 100644
--- a/src/web/app/desktop/views/components/settings.api.vue
+++ b/src/web/app/desktop/views/components/settings.api.vue
@@ -1,6 +1,6 @@
 <template>
 <div class="root api">
-	<p>Token: <code>{{ os.i.token }}</code></p>
+	<p>Token: <code>{{ os.i.account.token }}</code></p>
 	<p>%i18n:desktop.tags.mk-api-info.intro%</p>
 	<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:desktop.tags.mk-api-info.caution%</p></div>
 	<p>%i18n:desktop.tags.mk-api-info.regeneration-of-token%</p>
diff --git a/src/web/app/desktop/views/components/settings.profile.vue b/src/web/app/desktop/views/components/settings.profile.vue
index 23a166376..67a211c79 100644
--- a/src/web/app/desktop/views/components/settings.profile.vue
+++ b/src/web/app/desktop/views/components/settings.profile.vue
@@ -24,7 +24,7 @@
 	<button class="ui primary" @click="save">%i18n:desktop.tags.mk-profile-setting.save%</button>
 	<section>
 		<h2>その他</h2>
-		<mk-switch v-model="os.i.is_bot" @change="onChangeIsBot" text="このアカウントはbotです"/>
+		<mk-switch v-model="os.i.account.is_bot" @change="onChangeIsBot" text="このアカウントはbotです"/>
 	</section>
 </div>
 </template>
@@ -43,9 +43,9 @@ export default Vue.extend({
 	},
 	created() {
 		this.name = (this as any).os.i.name;
-		this.location = (this as any).os.i.profile.location;
+		this.location = (this as any).os.i.account.profile.location;
 		this.description = (this as any).os.i.description;
-		this.birthday = (this as any).os.i.profile.birthday;
+		this.birthday = (this as any).os.i.account.profile.birthday;
 	},
 	methods: {
 		updateAvatar() {
@@ -63,7 +63,7 @@ export default Vue.extend({
 		},
 		onChangeIsBot() {
 			(this as any).api('i/update', {
-				is_bot: (this as any).os.i.is_bot
+				is_bot: (this as any).os.i.account.is_bot
 			});
 		}
 	}
diff --git a/src/web/app/desktop/views/components/settings.vue b/src/web/app/desktop/views/components/settings.vue
index 950e60fb3..3e6a477ce 100644
--- a/src/web/app/desktop/views/components/settings.vue
+++ b/src/web/app/desktop/views/components/settings.vue
@@ -20,7 +20,7 @@
 
 		<section class="web" v-show="page == 'web'">
 			<h1>動作</h1>
-			<mk-switch v-model="os.i.client_settings.fetchOnScroll" @change="onChangeFetchOnScroll" text="スクロールで自動読み込み">
+			<mk-switch v-model="os.i.account.client_settings.fetchOnScroll" @change="onChangeFetchOnScroll" text="スクロールで自動読み込み">
 				<span>ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。</span>
 			</mk-switch>
 			<mk-switch v-model="autoPopout" text="ウィンドウの自動ポップアウト">
@@ -33,11 +33,11 @@
 			<div class="div">
 				<button class="ui button" @click="customizeHome">ホームをカスタマイズ</button>
 			</div>
-			<mk-switch v-model="os.i.client_settings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="タイムライン上部に投稿フォームを表示する"/>
-			<mk-switch v-model="os.i.client_settings.showMaps" @change="onChangeShowMaps" text="マップの自動展開">
+			<mk-switch v-model="os.i.account.client_settings.showPostFormOnTopOfTl" @change="onChangeShowPostFormOnTopOfTl" text="タイムライン上部に投稿フォームを表示する"/>
+			<mk-switch v-model="os.i.account.client_settings.showMaps" @change="onChangeShowMaps" text="マップの自動展開">
 				<span>位置情報が添付された投稿のマップを自動的に展開します。</span>
 			</mk-switch>
-			<mk-switch v-model="os.i.client_settings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="ウィンドウのタイトルバーにグラデーションを使用"/>
+			<mk-switch v-model="os.i.account.client_settings.gradientWindowHeader" @change="onChangeGradientWindowHeader" text="ウィンドウのタイトルバーにグラデーションを使用"/>
 		</section>
 
 		<section class="web" v-show="page == 'web'">
@@ -57,7 +57,7 @@
 
 		<section class="web" v-show="page == 'web'">
 			<h1>モバイル</h1>
-			<mk-switch v-model="os.i.client_settings.disableViaMobile" @change="onChangeDisableViaMobile" text="「モバイルからの投稿」フラグを付けない"/>
+			<mk-switch v-model="os.i.account.client_settings.disableViaMobile" @change="onChangeDisableViaMobile" text="「モバイルからの投稿」フラグを付けない"/>
 		</section>
 
 		<section class="web" v-show="page == 'web'">
@@ -86,7 +86,7 @@
 
 		<section class="notification" v-show="page == 'notification'">
 			<h1>通知</h1>
-			<mk-switch v-model="os.i.settings.auto_watch" @change="onChangeAutoWatch" text="投稿の自動ウォッチ">
+			<mk-switch v-model="os.i.account.settings.auto_watch" @change="onChangeAutoWatch" text="投稿の自動ウォッチ">
 				<span>リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。</span>
 			</mk-switch>
 		</section>
diff --git a/src/web/app/desktop/views/components/timeline.vue b/src/web/app/desktop/views/components/timeline.vue
index b6b28c352..47a9688b6 100644
--- a/src/web/app/desktop/views/components/timeline.vue
+++ b/src/web/app/desktop/views/components/timeline.vue
@@ -107,7 +107,7 @@ export default Vue.extend({
 			this.fetch();
 		},
 		onScroll() {
-			if ((this as any).os.i.client_settings.fetchOnScroll !== false) {
+			if ((this as any).os.i.account.client_settings.fetchOnScroll !== false) {
 				const current = window.scrollY + window.innerHeight;
 				if (current > document.body.offsetHeight - 8) this.more();
 			}
diff --git a/src/web/app/desktop/views/components/ui.header.vue b/src/web/app/desktop/views/components/ui.header.vue
index 5425ec876..8af0e2fbe 100644
--- a/src/web/app/desktop/views/components/ui.header.vue
+++ b/src/web/app/desktop/views/components/ui.header.vue
@@ -44,9 +44,9 @@ export default Vue.extend({
 	},
 	mounted() {
 		if ((this as any).os.isSignedIn) {
-			const ago = (new Date().getTime() - new Date((this as any).os.i.last_used_at).getTime()) / 1000
+			const ago = (new Date().getTime() - new Date((this as any).os.i.account.last_used_at).getTime()) / 1000
 			const isHisasiburi = ago >= 3600;
-			(this as any).os.i.last_used_at = new Date();
+			(this as any).os.i.account.last_used_at = new Date();
 			if (isHisasiburi) {
 				(this.$refs.welcomeback as any).style.display = 'block';
 				(this.$refs.main as any).style.overflow = 'hidden';
diff --git a/src/web/app/desktop/views/components/widget-container.vue b/src/web/app/desktop/views/components/widget-container.vue
index c08e58e21..dd42be63b 100644
--- a/src/web/app/desktop/views/components/widget-container.vue
+++ b/src/web/app/desktop/views/components/widget-container.vue
@@ -24,8 +24,8 @@ export default Vue.extend({
 	computed: {
 		withGradient(): boolean {
 			return (this as any).os.isSignedIn
-				? (this as any).os.i.client_settings.gradientWindowHeader != null
-					? (this as any).os.i.client_settings.gradientWindowHeader
+				? (this as any).os.i.account.client_settings.gradientWindowHeader != null
+					? (this as any).os.i.account.client_settings.gradientWindowHeader
 					: false
 				: false;
 		}
diff --git a/src/web/app/desktop/views/components/window.vue b/src/web/app/desktop/views/components/window.vue
index 0f89aa3e4..75f725d4b 100644
--- a/src/web/app/desktop/views/components/window.vue
+++ b/src/web/app/desktop/views/components/window.vue
@@ -92,8 +92,8 @@ export default Vue.extend({
 		},
 		withGradient(): boolean {
 			return (this as any).os.isSignedIn
-				? (this as any).os.i.client_settings.gradientWindowHeader != null
-					? (this as any).os.i.client_settings.gradientWindowHeader
+				? (this as any).os.i.account.client_settings.gradientWindowHeader != null
+					? (this as any).os.i.account.client_settings.gradientWindowHeader
 					: false
 				: false;
 		}
diff --git a/src/web/app/desktop/views/pages/user/user.header.vue b/src/web/app/desktop/views/pages/user/user.header.vue
index b2119e52e..63542055d 100644
--- a/src/web/app/desktop/views/pages/user/user.header.vue
+++ b/src/web/app/desktop/views/pages/user/user.header.vue
@@ -9,7 +9,7 @@
 		<div class="title">
 			<p class="name">{{ user.name }}</p>
 			<p class="username">@{{ user.username }}</p>
-			<p class="location" v-if="user.profile.location">%fa:map-marker%{{ user.profile.location }}</p>
+			<p class="location" v-if="user.account.profile.location">%fa:map-marker%{{ user.account.profile.location }}</p>
 		</div>
 		<footer>
 			<router-link :to="`/${user.username}`" :data-active="$parent.page == 'home'">%fa:home%概要</router-link>
diff --git a/src/web/app/desktop/views/pages/user/user.home.vue b/src/web/app/desktop/views/pages/user/user.home.vue
index 17aa83201..592d5cca6 100644
--- a/src/web/app/desktop/views/pages/user/user.home.vue
+++ b/src/web/app/desktop/views/pages/user/user.home.vue
@@ -5,7 +5,7 @@
 			<x-profile :user="user"/>
 			<x-photos :user="user"/>
 			<x-followers-you-know v-if="os.isSignedIn && os.i.id != user.id" :user="user"/>
-			<p>%i18n:desktop.tags.mk-user.last-used-at%: <b><mk-time :time="user.last_used_at"/></b></p>
+			<p>%i18n:desktop.tags.mk-user.last-used-at%: <b><mk-time :time="user.account.last_used_at"/></b></p>
 		</div>
 	</div>
 	<main>
diff --git a/src/web/app/desktop/views/pages/user/user.profile.vue b/src/web/app/desktop/views/pages/user/user.profile.vue
index ceca829ac..1e7cb455b 100644
--- a/src/web/app/desktop/views/pages/user/user.profile.vue
+++ b/src/web/app/desktop/views/pages/user/user.profile.vue
@@ -7,11 +7,11 @@
 		<p v-if="!user.is_muted"><a @click="mute">%i18n:desktop.tags.mk-user.mute%</a></p>
 	</div>
 	<div class="description" v-if="user.description">{{ user.description }}</div>
-	<div class="birthday" v-if="user.profile.birthday">
-		<p>%fa:birthday-cake%{{ user.profile.birthday.replace('-', '年').replace('-', '月') + '日' }} ({{ age }}歳)</p>
+	<div class="birthday" v-if="user.account.profile.birthday">
+		<p>%fa:birthday-cake%{{ user.account.profile.birthday.replace('-', '年').replace('-', '月') + '日' }} ({{ age }}歳)</p>
 	</div>
-	<div class="twitter" v-if="user.twitter">
-		<p>%fa:B twitter%<a :href="`https://twitter.com/${user.twitter.screen_name}`" target="_blank">@{{ user.twitter.screen_name }}</a></p>
+	<div class="twitter" v-if="user.account.twitter">
+		<p>%fa:B twitter%<a :href="`https://twitter.com/${user.account.twitter.screen_name}`" target="_blank">@{{ user.account.twitter.screen_name }}</a></p>
 	</div>
 	<div class="status">
 		<p class="posts-count">%fa:angle-right%<a>{{ user.posts_count }}</a><b>投稿</b></p>
@@ -31,7 +31,7 @@ export default Vue.extend({
 	props: ['user'],
 	computed: {
 		age(): number {
-			return age(this.user.profile.birthday);
+			return age(this.user.account.profile.birthday);
 		}
 	},
 	methods: {
diff --git a/src/web/app/mobile/views/components/post-detail.vue b/src/web/app/mobile/views/components/post-detail.vue
index d51bfbc0e..4b0b59eff 100644
--- a/src/web/app/mobile/views/components/post-detail.vue
+++ b/src/web/app/mobile/views/components/post-detail.vue
@@ -144,7 +144,7 @@ export default Vue.extend({
 
 		// Draw map
 		if (this.p.geo) {
-			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.client_settings.showMaps : true;
+			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.client_settings.showMaps : true;
 			if (shouldShowMap) {
 				(this as any).os.getGoogleMaps().then(maps => {
 					const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude);
diff --git a/src/web/app/mobile/views/components/post-form.vue b/src/web/app/mobile/views/components/post-form.vue
index 5b47caebc..2aa3c6f6c 100644
--- a/src/web/app/mobile/views/components/post-form.vue
+++ b/src/web/app/mobile/views/components/post-form.vue
@@ -111,7 +111,7 @@ export default Vue.extend({
 		},
 		post() {
 			this.posting = true;
-			const viaMobile = (this as any).os.i.client_settings.disableViaMobile !== true;
+			const viaMobile = (this as any).os.i.account.client_settings.disableViaMobile !== true;
 			(this as any).api('posts/create', {
 				text: this.text == '' ? undefined : this.text,
 				media_ids: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
diff --git a/src/web/app/mobile/views/components/post.vue b/src/web/app/mobile/views/components/post.vue
index d464f6460..8df4dbf22 100644
--- a/src/web/app/mobile/views/components/post.vue
+++ b/src/web/app/mobile/views/components/post.vue
@@ -22,7 +22,7 @@
 		<div class="main">
 			<header>
 				<router-link class="name" :to="`/${p.user.username}`">{{ p.user.name }}</router-link>
-				<span class="is-bot" v-if="p.user.is_bot">bot</span>
+				<span class="is-bot" v-if="p.user.account.is_bot">bot</span>
 				<span class="username">@{{ p.user.username }}</span>
 				<div class="info">
 					<span class="mobile" v-if="p.via_mobile">%fa:mobile-alt%</span>
@@ -137,7 +137,7 @@ export default Vue.extend({
 
 		// Draw map
 		if (this.p.geo) {
-			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.client_settings.showMaps : true;
+			const shouldShowMap = (this as any).os.isSignedIn ? (this as any).os.i.account.client_settings.showMaps : true;
 			if (shouldShowMap) {
 				(this as any).os.getGoogleMaps().then(maps => {
 					const uluru = new maps.LatLng(this.p.geo.latitude, this.p.geo.longitude);
diff --git a/src/web/app/mobile/views/components/ui.header.vue b/src/web/app/mobile/views/components/ui.header.vue
index 1ccbd5c95..66e10a0f8 100644
--- a/src/web/app/mobile/views/components/ui.header.vue
+++ b/src/web/app/mobile/views/components/ui.header.vue
@@ -57,9 +57,9 @@ export default Vue.extend({
 				}
 			});
 
-			const ago = (new Date().getTime() - new Date((this as any).os.i.last_used_at).getTime()) / 1000
+			const ago = (new Date().getTime() - new Date((this as any).os.i.account.last_used_at).getTime()) / 1000
 			const isHisasiburi = ago >= 3600;
-			(this as any).os.i.last_used_at = new Date();
+			(this as any).os.i.account.last_used_at = new Date();
 			if (isHisasiburi) {
 				(this.$refs.welcomeback as any).style.display = 'block';
 				(this.$refs.main as any).style.overflow = 'hidden';
diff --git a/src/web/app/mobile/views/pages/home.vue b/src/web/app/mobile/views/pages/home.vue
index 44b072491..b110fc409 100644
--- a/src/web/app/mobile/views/pages/home.vue
+++ b/src/web/app/mobile/views/pages/home.vue
@@ -82,8 +82,8 @@ export default Vue.extend({
 		};
 	},
 	created() {
-		if ((this as any).os.i.client_settings.mobile_home == null) {
-			Vue.set((this as any).os.i.client_settings, 'mobile_home', [{
+		if ((this as any).os.i.account.client_settings.mobile_home == null) {
+			Vue.set((this as any).os.i.account.client_settings, 'mobile_home', [{
 				name: 'calendar',
 				id: 'a', data: {}
 			}, {
@@ -105,14 +105,14 @@ export default Vue.extend({
 				name: 'version',
 				id: 'g', data: {}
 			}]);
-			this.widgets = (this as any).os.i.client_settings.mobile_home;
+			this.widgets = (this as any).os.i.account.client_settings.mobile_home;
 			this.saveHome();
 		} else {
-			this.widgets = (this as any).os.i.client_settings.mobile_home;
+			this.widgets = (this as any).os.i.account.client_settings.mobile_home;
 		}
 
-		this.$watch('os.i.client_settings', i => {
-			this.widgets = (this as any).os.i.client_settings.mobile_home;
+		this.$watch('os.i.account.client_settings', i => {
+			this.widgets = (this as any).os.i.account.client_settings.mobile_home;
 		}, {
 			deep: true
 		});
@@ -157,15 +157,15 @@ export default Vue.extend({
 		},
 		onHomeUpdated(data) {
 			if (data.home) {
-				(this as any).os.i.client_settings.mobile_home = data.home;
+				(this as any).os.i.account.client_settings.mobile_home = data.home;
 				this.widgets = data.home;
 			} else {
-				const w = (this as any).os.i.client_settings.mobile_home.find(w => w.id == data.id);
+				const w = (this as any).os.i.account.client_settings.mobile_home.find(w => w.id == data.id);
 				if (w != null) {
 					w.data = data.data;
 					this.$refs[w.id][0].preventSave = true;
 					this.$refs[w.id][0].props = w.data;
-					this.widgets = (this as any).os.i.client_settings.mobile_home;
+					this.widgets = (this as any).os.i.account.client_settings.mobile_home;
 				}
 			}
 		},
@@ -194,7 +194,7 @@ export default Vue.extend({
 			this.saveHome();
 		},
 		saveHome() {
-			(this as any).os.i.client_settings.mobile_home = this.widgets;
+			(this as any).os.i.account.client_settings.mobile_home = this.widgets;
 			(this as any).api('i/update_mobile_home', {
 				home: this.widgets
 			});
diff --git a/src/web/app/mobile/views/pages/profile-setting.vue b/src/web/app/mobile/views/pages/profile-setting.vue
index f25d4bbe8..941165c99 100644
--- a/src/web/app/mobile/views/pages/profile-setting.vue
+++ b/src/web/app/mobile/views/pages/profile-setting.vue
@@ -53,9 +53,9 @@ export default Vue.extend({
 	},
 	created() {
 		this.name = (this as any).os.i.name;
-		this.location = (this as any).os.i.profile.location;
+		this.location = (this as any).os.i.account.profile.location;
 		this.description = (this as any).os.i.description;
-		this.birthday = (this as any).os.i.profile.birthday;
+		this.birthday = (this as any).os.i.account.profile.birthday;
 	},
 	mounted() {
 		document.title = 'Misskey | %i18n:mobile.tags.mk-profile-setting-page.title%';
diff --git a/src/web/app/mobile/views/pages/user.vue b/src/web/app/mobile/views/pages/user.vue
index 90f49a99a..9f677f6ca 100644
--- a/src/web/app/mobile/views/pages/user.vue
+++ b/src/web/app/mobile/views/pages/user.vue
@@ -18,11 +18,11 @@
 				</div>
 				<div class="description">{{ user.description }}</div>
 				<div class="info">
-					<p class="location" v-if="user.profile.location">
-						%fa:map-marker%{{ user.profile.location }}
+					<p class="location" v-if="user.account.profile.location">
+						%fa:map-marker%{{ user.account.profile.location }}
 					</p>
-					<p class="birthday" v-if="user.profile.birthday">
-						%fa:birthday-cake%{{ user.profile.birthday.replace('-', '年').replace('-', '月') + '日' }} ({{ age }}歳)
+					<p class="birthday" v-if="user.account.profile.birthday">
+						%fa:birthday-cake%{{ user.account.profile.birthday.replace('-', '年').replace('-', '月') + '日' }} ({{ age }}歳)
 					</p>
 				</div>
 				<div class="status">
@@ -74,7 +74,7 @@ export default Vue.extend({
 	},
 	computed: {
 		age(): number {
-			return age(this.user.profile.birthday);
+			return age(this.user.account.profile.birthday);
 		}
 	},
 	watch: {
diff --git a/src/web/app/mobile/views/pages/user/home.vue b/src/web/app/mobile/views/pages/user/home.vue
index fdbfd1bf5..dabb3f60b 100644
--- a/src/web/app/mobile/views/pages/user/home.vue
+++ b/src/web/app/mobile/views/pages/user/home.vue
@@ -31,7 +31,7 @@
 			<x-followers-you-know :user="user"/>
 		</div>
 	</section>
-	<p>%i18n:mobile.tags.mk-user-overview.last-used-at%: <b><mk-time :time="user.last_used_at"/></b></p>
+	<p>%i18n:mobile.tags.mk-user-overview.last-used-at%: <b><mk-time :time="user.account.last_used_at"/></b></p>
 </div>
 </template>
 
diff --git a/src/web/app/mobile/views/pages/welcome.vue b/src/web/app/mobile/views/pages/welcome.vue
index aa50b572e..563d2b28c 100644
--- a/src/web/app/mobile/views/pages/welcome.vue
+++ b/src/web/app/mobile/views/pages/welcome.vue
@@ -8,7 +8,7 @@
 			<form @submit.prevent="onSubmit">
 				<input v-model="username" type="text" pattern="^[a-zA-Z0-9-]+$" placeholder="ユーザー名" autofocus required @change="onUsernameChange"/>
 				<input v-model="password" type="password" placeholder="パスワード" required/>
-				<input v-if="user && user.two_factor_enabled" v-model="token" type="number" placeholder="トークン" required/>
+				<input v-if="user && user.account.two_factor_enabled" v-model="token" type="number" placeholder="トークン" required/>
 				<button type="submit" :disabled="signing">{{ signing ? 'ログインしています' : 'ログイン' }}</button>
 			</form>
 			<div>
@@ -70,7 +70,7 @@ export default Vue.extend({
 			(this as any).api('signin', {
 				username: this.username,
 				password: this.password,
-				token: this.user && this.user.two_factor_enabled ? this.token : undefined
+				token: this.user && this.user.account.two_factor_enabled ? this.token : undefined
 			}).then(() => {
 				location.reload();
 			}).catch(() => {
diff --git a/src/web/docs/api/entities/user.yaml b/src/web/docs/api/entities/user.yaml
index 528b9b0e1..f0d5fdbba 100644
--- a/src/web/docs/api/entities/user.yaml
+++ b/src/web/docs/api/entities/user.yaml
@@ -81,12 +81,6 @@ props:
     desc:
       ja: "自分がこのユーザーをミュートしているか"
       en: "Whether you muted this user"
-  - name: "last_used_at"
-    type: "date"
-    optional: false
-    desc:
-      ja: "最終利用日時"
-      en: "The last used date of this user"
   - name: "posts_count"
     type: "number"
     optional: false
@@ -111,49 +105,63 @@ props:
     desc:
       ja: "ドライブの容量(bytes)"
       en: "The capacity of drive of this user (bytes)"
-  - name: "is_bot"
-    type: "boolean"
-    optional: true
-    desc:
-      ja: "botか否か(自己申告であることに留意)"
-      en: "Whether is bot or not"
-  - name: "twitter"
-    type: "object"
-    optional: true
-    desc:
-      ja: "連携されているTwitterアカウント情報"
-      en: "The info of the connected twitter account of this user"
-    defName: "twitter"
-    def:
-      - name: "user_id"
-        type: "string"
-        optional: false
-        desc:
-          ja: "ユーザーID"
-          en: "The user ID"
-      - name: "screen_name"
-        type: "string"
-        optional: false
-        desc:
-          ja: "ユーザー名"
-          en: "The screen name of this user"
-  - name: "profile"
+  - name: "account"
     type: "object"
     optional: false
     desc:
-      ja: "プロフィール"
-      en: "The profile of this user"
-    defName: "profile"
+      ja: "このサーバーにおけるアカウント"
+      en: "The account of this user on this server"
+    defName: "account"
     def:
-      - name: "location"
-        type: "string"
+      - name: "last_used_at"
+        type: "date"
+        optional: false
+        desc:
+          ja: "最終利用日時"
+          en: "The last used date of this user"
+      - name: "is_bot"
+        type: "boolean"
         optional: true
         desc:
-          ja: "場所"
-          en: "The location of this user"
-      - name: "birthday"
-        type: "string"
+          ja: "botか否か(自己申告であることに留意)"
+          en: "Whether is bot or not"
+      - name: "twitter"
+        type: "object"
         optional: true
         desc:
-          ja: "誕生日 (YYYY-MM-DD)"
-          en: "The birthday of this user (YYYY-MM-DD)"
+          ja: "連携されているTwitterアカウント情報"
+          en: "The info of the connected twitter account of this user"
+        defName: "twitter"
+        def:
+          - name: "user_id"
+            type: "string"
+            optional: false
+            desc:
+              ja: "ユーザーID"
+              en: "The user ID"
+          - name: "screen_name"
+            type: "string"
+            optional: false
+            desc:
+              ja: "ユーザー名"
+              en: "The screen name of this user"
+      - name: "profile"
+        type: "object"
+        optional: false
+        desc:
+          ja: "プロフィール"
+          en: "The profile of this user"
+        defName: "profile"
+        def:
+          - name: "location"
+            type: "string"
+            optional: true
+            desc:
+              ja: "場所"
+              en: "The location of this user"
+          - name: "birthday"
+            type: "string"
+            optional: true
+            desc:
+              ja: "誕生日 (YYYY-MM-DD)"
+              en: "The birthday of this user (YYYY-MM-DD)"
diff --git a/test/api.js b/test/api.js
index 500b9adb7..9e55dd991 100644
--- a/test/api.js
+++ b/test/api.js
@@ -30,7 +30,7 @@ const async = fn => (done) => {
 
 const request = (endpoint, params, me) => new Promise((ok, ng) => {
 	const auth = me ? {
-		i: me.token
+		i: me.account.token
 	} : {};
 
 	_chai.request(server)
@@ -136,8 +136,10 @@ describe('API', () => {
 	describe('i/update', () => {
 		it('アカウント設定を更新できる', async(async () => {
 			const me = await insertSakurako({
-				profile: {
-					gender: 'female'
+				account: {
+					profile: {
+						gender: 'female'
+					}
 				}
 			});
 
@@ -153,10 +155,10 @@ describe('API', () => {
 			res.should.have.status(200);
 			res.body.should.be.a('object');
 			res.body.should.have.property('name').eql(myName);
-			res.body.should.have.property('profile').a('object');
-			res.body.should.have.nested.property('profile.location').eql(myLocation);
-			res.body.should.have.nested.property('profile.birthday').eql(myBirthday);
-			res.body.should.have.nested.property('profile.gender').eql('female');
+			res.body.should.have.nested.property('account.profile').a('object');
+			res.body.should.have.nested.property('account.profile.location').eql(myLocation);
+			res.body.should.have.nested.property('account.profile.birthday').eql(myBirthday);
+			res.body.should.have.nested.property('account.profile.gender').eql('female');
 		}));
 
 		it('名前を空白にできない', async(async () => {
@@ -176,8 +178,8 @@ describe('API', () => {
 			}, me);
 			res.should.have.status(200);
 			res.body.should.be.a('object');
-			res.body.should.have.property('profile').a('object');
-			res.body.should.have.nested.property('profile.birthday').eql(null);
+			res.body.should.have.nested.property('account.profile').a('object');
+			res.body.should.have.nested.property('account.profile.birthday').eql(null);
 		}));
 
 		it('不正な誕生日の形式で怒られる', async(async () => {
@@ -764,7 +766,7 @@ describe('API', () => {
 			const me = await insertSakurako();
 			const res = await _chai.request(server)
 				.post('/drive/files/create')
-				.field('i', me.token)
+				.field('i', me.account.token)
 				.attach('file', fs.readFileSync(__dirname + '/resources/Lenna.png'), 'Lenna.png');
 			res.should.have.status(200);
 			res.body.should.be.a('object');
@@ -1138,27 +1140,47 @@ describe('API', () => {
 	});
 });
 
+function deepAssign(destination, ...sources) {
+	for (const source of sources) {
+		for (const key in source) {
+			const destinationChild = destination[key];
+
+			if (typeof destinationChild === 'object' && destinationChild != null) {
+				deepAssign(destinationChild, source[key]);
+			} else {
+				destination[key] = source[key];
+			}
+		}
+	}
+
+	return destination;
+}
+
 function insertSakurako(opts) {
-	return db.get('users').insert(Object.assign({
-		token: '!00000000000000000000000000000000',
+	return db.get('users').insert(deepAssign({
 		username: 'sakurako',
 		username_lower: 'sakurako',
-		password: '$2a$08$FnHXg3tP.M/kINWgQSXNqeoBsiVrkj.ecXX8mW9rfBzMRkibYfjYy', // HimawariDaisuki06160907
-		profile: {},
-		settings: {},
-		client_settings: {}
+		account: {
+			token: '!00000000000000000000000000000000',
+			password: '$2a$08$FnHXg3tP.M/kINWgQSXNqeoBsiVrkj.ecXX8mW9rfBzMRkibYfjYy', // HimawariDaisuki06160907
+			profile: {},
+			settings: {},
+			client_settings: {}
+		}
 	}, opts));
 }
 
 function insertHimawari(opts) {
-	return db.get('users').insert(Object.assign({
-		token: '!00000000000000000000000000000001',
+	return db.get('users').insert(deepAssign({
 		username: 'himawari',
 		username_lower: 'himawari',
-		password: '$2a$08$OPESxR2RE/ZijjGanNKk6ezSqGFitqsbZqTjWUZPLhORMKxHCbc4O', // ilovesakurako
-		profile: {},
-		settings: {},
-		client_settings: {}
+		account: {
+			token: '!00000000000000000000000000000001',
+			password: '$2a$08$OPESxR2RE/ZijjGanNKk6ezSqGFitqsbZqTjWUZPLhORMKxHCbc4O', // ilovesakurako
+			profile: {},
+			settings: {},
+			client_settings: {}
+		}
 	}, opts));
 }
 
@@ -1171,14 +1193,14 @@ function insertDriveFile(opts) {
 }
 
 function insertDriveFolder(opts) {
-	return db.get('drive_folders').insert(Object.assign({
+	return db.get('drive_folders').insert(deepAssign({
 		name: 'my folder',
 		parent_id: null
 	}, opts));
 }
 
 function insertApp(opts) {
-	return db.get('apps').insert(Object.assign({
+	return db.get('apps').insert(deepAssign({
 		name: 'my app',
 		secret: 'mysecret'
 	}, opts));
diff --git a/tools/migration/shell.1522038492.user-account.js b/tools/migration/shell.1522038492.user-account.js
new file mode 100644
index 000000000..056c29e8e
--- /dev/null
+++ b/tools/migration/shell.1522038492.user-account.js
@@ -0,0 +1,41 @@
+db.users.dropIndex({ token: 1 });
+
+db.users.find({}).forEach(function(user) {
+	print(user._id);
+	db.users.update({ _id: user._id }, {
+		$unset: {
+			email: '',
+			links: '',
+			password: '',
+			token: '',
+			twitter: '',
+			line: '',
+			profile: '',
+			last_used_at: '',
+			is_bot: '',
+			is_pro: '',
+			two_factor_secret: '',
+			two_factor_enabled: '',
+			client_settings: '',
+			settings: ''
+		},
+		$set: {
+			account: {
+				email: user.email,
+				links: user.links,
+				password: user.password,
+				token: user.token,
+				twitter: user.twitter,
+				line: user.line,
+				profile: user.profile,
+				last_used_at: user.last_used_at,
+				is_bot: user.is_bot,
+				is_pro: user.is_pro,
+				two_factor_secret: user.two_factor_secret,
+				two_factor_enabled: user.two_factor_enabled,
+				client_settings: user.client_settings,
+				settings: user.settings
+			}
+		}
+	}, false, false);
+});