@Override
	public WebPage onRedirect(Map<String, String> request) {
		token = new OAuth2Token();
		error = new OAuth2Error();
		RedirectWebPage page = new RedirectWebPage();
		page.addHeader("Content-type", "text/html; charset=utf-8");
		page.setTitle("Error occured");
		if (request.containsKey("state")) { // state parameter found
			if (request.get("state").equals(state)) { // state parameter matches expected value
				if (request.containsKey("error")) { // error during authorization
					error.setType(OAuth2ErrorType.valueOf(request.get("error").toUpperCase()));
					String errorType = error.getType().toString();
					page.addBodyLine("<p id=\"error\">Error occured during authorization.</p>");
					page.addBodyLine("<p>");
					if (errorType != null) {
						errorType = "<strong>" + errorType.replace('_', ' ') + "</strong>";
						if (request.containsKey("error_description")) {
							error.setDescription(request.get("error_description"));
							errorType += ": " + error.getDescription();
						}
						page.addBodyLine(errorType);
					}
					if (request.containsKey("error_uri")) {
						error.setUri(request.get("error_uri"));
						page.addBodyLine("<br />");
						page.addBodyLine("For more information, visit: <a href=\"" + error.getUri() + "\">" + request.get("error_uri") + "</a>");
					}
					page.addBodyLine("</p>");
				} else {
					if (request.containsKey("code")) { // successful authorization
						tokenParams.put("code", request.get("code"));
						if (!tokenRequest.isAlive()) {
							tokenRequest.start();
						}
						page.setTitle("Authorization successful");
						page.addBodyLine("<p id=\"success\">Authorization successful.</p>");
						page.addBodyLine("<p>You may now close this page and return to the application.</p>");
					} else { // authorization code not found in the request
						error.setType(OAuth2ErrorType.CODE_MISSING);
						error.setDescription("Authorization code missing.");
						page.addBodyLine("<p id=\"error\">Error occured during authorization.</p>");
						page.addBodyLine("<p><strong>" + error.getType().toString().replace('_', ' ') + "</strong>: " + error.getDescription() + "</p>");
					}
				}
			} else { // state parameter doesn't match the actual state
				error.setType(OAuth2ErrorType.STATE_MISMATCH);
				error.setDescription("Mismatch in <code>state</code> parameter.");
				page.addBodyLine("<p id=\"error\">Error occured during authorization.</p>");
				page.addBodyLine("<p><strong>" + error.getType().toString().replace('_', ' ') + "</strong>: " + error.getDescription() + "</p>");
			}
		} else { // state parameter not set in the request
			error.setType(OAuth2ErrorType.STATE_MISSING);
			error.setDescription("Missing <code>state</code> parameter.");
			page.addBodyLine("<p id=\"error\">Error occured during authorization.</p>");
			page.addBodyLine("<p><strong>" + error.getType().toString().replace('_', ' ') + "</strong>: " + error.getDescription() + "</p>");
		}
		if (error.getType() != OAuth2ErrorType.SUCCESS) {
			/* notify all waiting objects */
			synchronized (waitObject) {
				ready = true;
				waitObject.notifyAll();
			}
		}
		return page;
	}