Exam 2023-03-23

Here you find sample answers and marking guidelines to the questions on the exam 2023-03-23.


Start by reading through all questions. Peter will visit the exam 45 minutes after it has started to clarify the questions you find unclear.

Max score is 25 points.

  • For grade 3, 40% of max score (10 points) is required
  • For grade 4, 60% of max score (15 points) is required
  • For grade 5, 80% of max score (20 points) is required

You are not allowed to use anything else except:

  • The computer you sit at to only answer the questions on this exam
  • A dictionary to translate to/from English from/to your native language
  • Pen and paper to sketch with (should not be submitted)

Write your answers in either English or Swedish. If you write your answers in Swedish, make sure to not introduce any translation confusement. Write proper sentences (spelling, upper/lower case characters, punctuation, etc.). Answers that do not do this good enough/are vague/are not understandable cannot receive full score on the questions,

Answers that are more or less copies of sample answers given to you or copies of text found somewhere else will be rewarded 0 points. Use your own words to answer the questions.

Good luck!

Client-Side JS

Question 1 (1p)

Question

Explain why most websites with Client-Side JS code need to listen for the DOMContentLoaded event.

Sample answer

When using Client-Side JavaScript, one often needs to modify the Document Object Model (DOM), such as inserting an HTML element into it, or remove an HTML element from it, etc. To carry out these operations, we need references to the HTML elements in the DOM we want to work with. To obtain those references, we can use document methods such as getElementById() and querySelector(). However, the call to these methods must happen when the web browser is done parsing the HTML code on the webpage (hence is done building the DOM), and not before that. So we need to listen to the DOMContentLoaded event so our code that makes use of these methods will run after the web browser has created the HTML elements in the DOM.

Marking guidelines

  • 1 point for correct explanation

Question 2 (1p)

Question

Alice has a webpage with the following HTML code in <body>:

<input type="number" id="number1">
<input type="number" id="number2">
<button id="showSum">Show sum</button>

The user should enter two numbers in the <input> elements, and then when the user clicks the button, the sum should be shown in an alert dialog (an alert dialog can be shown by calling the alert() function). To make that happen, she adds the following HTML code to the page:

<script>
	
	document.addEventListener('DOMContentLoaded', function(){
		
		const number1 = parseInt(document.getElementById('number1').value, 10)
		const number2 = parseInt(document.getElementById('number2').value, 10)
		
		document.getElementById('showSum').addEventListener('click', function(){
			
			alert(number1 + number2)
			
		})
		
	})
	
</script>

When the button is clicked, an alert dialog is shown, but it does not display the sum of the numbers the user has entered. Explain what Alice has done wrong, and suggest how the code should be changed to work as it should.

Sample answer

The problem is that the values in the <input> elements are read when the DOMContentLoaded event happens, and at that time, the user hasn't entered any numbers in them yet. The numbers should instead be read when the click event happens on the <button>, so moving the two lines of code creating the two variables into the innermost function would solve the problem.

Marking guidelines

  • 0.5 points for explaining the problem
  • 0.5 points for also explaining a solution
  • -0.1 points for each claim that is not true (except what parseInt(inputField.value, 10 evaluates to initially)

Question 3 (1p)

Question

When the user clicks on an anchor element on a webpage, an event is fired by the web browser. What is the name of that event?

Note: Spelling must be correct to get any points

Sample answer

click

Marking guidelines

  • 1 point for correct name (spelling must be correct)

Frontend framework

Question 4 (2p)

Question

In a frontend framework of your choice (name which one you choose), implement a component that contains two <input> elements the user can use to enter two numbers. The component should also contain a <span> element that automatically shows the sum of the entered numbers (should be updated automatically as soon as the user changes one of the numbers in the <input> elements).

Sample answer

In Svelte:

<script>
    
    let leftTerm = 0
    let rightTerm = 0
    
</script>

<input type="number" bind:value={leftTerm}> +
<input type="number" bind:value={rightTerm}> =
<span>{leftTerm + rightTerm}</span>

Marking guidelines

  • 2 points for an answer that is largely correct
  • Point reductions for errors:
    • -0.5 points for not naming which framework that is used
    • -0.25 points for using var when it's better to use let
    • In Svelte:
      • -0.25 points for not having the <script> element
      • -0.25 points for using const instead of let for the variables
      • -0.25 points for not using type="number"
      • -0.25 points for binding to the wrong variables
      • -0.25 points for using the wrong syntax for binding the variables to the input elements, but close to correct
      • -0.25 points for listening to the change event wrong
      • -0.25 points for using the wrong syntax to show the sum
      • -0.25 points for a sum variable that is not recomputed when the number variables change
    • In React:
      • -0.25 points for forgetting function keyword
      • -0.25 points for creating state outside the component
      • -0.25 points for creating state for sum (no point in doing that, ordinary variable suffice, and you open up for the possibility that someone changes the sum without changing the number variables, which makes no sense)
      • -0.25 points for not setting the value attribute to the correct value
      • -0.25 points for setting the onChange handler wrong

HTTP/REST API

Question 5 (1p)

Question

Match each status code with its corresponding reason phrase.

Status codes:

  • 200
  • 201
  • 204
  • 400
  • 404

Reason Phrases:

  • OK
  • Created
  • No Content
  • Bad Request
  • Not Found

You will get:

  • 1 point for all correct

Sample answer

  • 200 - OK
  • 201 - Created
  • 204 - No Content
  • 400 - Bad Request
  • 404 - Not Found

Marking guidelines

  • 1 point for all correct

Question 6 (1p)

Question

In a REST API, to create a new account, one should send an HTTP request like the one below (WORDS_WRITTEN_LIKE_THIS are placeholders for actual values).

POST /create-account
Host: ACTUAL_DOMAIN
Content-Type: application/json
Content-Length: ACTUAL_LENGTH

{"username": "ACTUAL_USERNAME", "password": "ACTUAL_PASSWORD"}

Is this HTTP request good designed? Justify your answer.

Sample answer

No, it is not good designed, because the URL doesn't identify resources, but instead indicates what the request is about. The URL should only identify resources, the method should indicate what to do. So, if the request is about creating a new resource, the URL should rather identify the collection of resources the new resources should be added to, i.e. /accounts in this case.

Marking guidelines

  • 1 point for justifying why the URL is bad
  • -0.1 points for stating something strange/that is not true

Question 7 (1p)

Question

In REST, explain what a constraint is.

Sample answer

A constraint is like a rule that you should follow, and if you do follow it, it will help preventing you from building a bad solution from a certain point of view, such as preventing you from building a solution that is not scalable.

Marking guidelines

  • 1 point for a correct explanation

Question 8 (3p)

Question

Name and describe each constraint REST consists of.

Sample answer

See Chapter 5.1 Deriving RESTopen in new window in Roy Thomas Fielding's dissertation Architectural Styles and the Design of Network-based Software Architectures.

Marking guidelines

  • 0.25 points for each correct name
  • 0.25 points for each correct description

Question 9 (3p)

Question

Describe the parts a JWT consists of. Then also explain why JWTs are secure to use (how a server can trust a JWT it receives from a client).

Sample answer

For a description of the parts, see Chapter 3.1. Example JWTopen in new window in the JSON Web Token (JWT) specification.

When the server signs the JWT, it will compute a hash from the Header, the Payload and a secret only the server knows. When the server receives a JWT from a client, it will compute the hash again from the Header, the Payload and the secret only the server knows. If the computed hash isn't the same as the signature in the received JWT, then server knows the JWT was created with another secret, hence not created by the server itself, and the server won't trust the token. Otherwise it can trust that the JWT was created by the server itself (under the assumption no one knows the secret on the server, or has been lucky using the same one).

Marking guidelines

  • 0.25 points for each name
  • 0.25 points for each description/purpose
  • 0.25 points for each how to generate the parts (JSON, base64, etc.)
  • 0.75 points for explaining how a server can trust a JWT/discover a tempered JWT

Question 10 (3p)

Question

In OAuth 2.0, name and describe the 4 different roles that exists. Then also describe how the Authorization Code flow works.

Sample answer

For the roles, see Chapter 1.1. Rolesopen in new window in the OAuth 2.0 specification.

For the Authorization Code flow, see Chapter 4.1. Authorization Code Grantopen in new window in the OAuth 2.0 specification.

Marking guidelines

  • Roles:
    • 0.25 points for each correct name
    • 0.25 points for each correct description
  • Authorization Code flow:
    • 1 point for full description with most events ("trades") happening (small point deduction for small misses)

Question 11 (1p)

Question

Give an example of a value that makes sense to put in an ID Token, but that most likely won't be needed in an Access Token. Justify your answer.

Sample answer

Since ID Tokens should contain information about the account a user has logged in to, it makes sense to put information such as the user's first name in it.

Access Tokens on the other hand should contain information the server can use to figure out what a user is allowed to do, and that is probably independent of the user's first name, so that is probably not put in an Access Token.

So an example is the user's first name, such as Alice.

Authentication VS Authorization

Many students use the word authentication wrong in their answers. Authentication happens when a user logs in, and proves ownership of an identity (for example by providing username and password), and thereafter obtains the token(s). When a user uses an access token, authorization happens (the user proves that it's authorized to send the request).

This time, no point reduction has been made for using the terms wrong, but think about this for the future.

Account id

Some students claim that a user's account id makes sense to put in the ID Token, but not in an Access Token. That usually makes little sense, since the server usually must know which account the user has logged in to during the authorization process, so the user's account id usually needs to be stored in the Access Token as well.

Marking guidelines

  • 1 point for valid example and valid justification, OR
  • 0.5 points for writing a valid justification, but without giving an example of a value (does not to have to be as specific as Alice, first name is accepted)
  • -0.1 points for claiming something that is incorrect

Question 12 (1p)

Question

Does it make sense to put the user's plain text password in an ID Token or in an Access Token? Justify your answer.

Sample answer

No, because there is no use-case for putting the user's password in the ID Token (the whole point with OpenID Connect is to let users login with their account on another platform without exposing their password on that platform), and nor is the user's password needed in an Access Token during the authorization process.

Also, one should never store users' passwords in plain text.

Marking guidelines

  • 1 point for correct answer and valid justification
  • -0.1 points for claiming something that is not true
  • 0 points to answers suggesting that one can store the encrypted/hashed version of the password in any of the tokens

Question 13 (1p)

Question

In Client-Side JS, give an example of/describe an HTTP request that will always trigger the web browser to send a CORS pre-flight request.

Sample answer

An HTTP request to a domain other than the one the Client-Side JS comes from and that uses the method PUT.

Marking guidelines

Note!

Most students didn't mention that the request must go to a different domain (so the Same-Origin Policy kicks in, and CORS is needed), but this time you can get full score on the question even without having mentioned that.

  • 1 point for correct example/description
  • -0.1 points for claiming something small that is incorrect, but otherwise provide a correct example/description

Docker

Question 14 (1p)

Question

When using Docker Compose, each service entered in the compose.yaml file can have its own volumes section. Explain what that section can be used for.

Sample answer

When an application in a Docker container opens a path leading to a file or folder, that path does by default lead to a file or folder on the file system in the container. By adding a value to the volumes section in the compose.yaml file, you can make a path in the container lead to a file or folder on the host computer running Docker instead.

So, by using volumes, an application in a container can get access to a part of the file system on the host computer, and for example store data there.

Marking guidelines

  • 1 point for correct answer, OR
  • 0.5 points for saying something vague about giving the container access to the latest version of code stored on the file system on the host computer

Question 15 (1p)

Question

Explain when and why you need to use port mapping in Docker, and explain how it works (using words, not commands).

Sample answer

A Docker container is an isolated environment; an app running inside the container has (by default) not access to anything on the host computer, and nor (by default) does the host computer have access to anything inside the container. This is problematic when the app in the container is a web app, and we want to use a web browser on the host computer to send HTTP requests to it.

In such situations, we can use port mapping to make the container a little bit less isolated, and allow such communication. Using port mapping, we can tell Docker that one port on the host computer, for example port 5555, should be mapped to one port in a container, for example port 8080. This way, the web browser on the host computer can send HTTP requests on port 5555, and the web app in the container will receive those requests on port 8080 in the container.

Marking guidelines

  • 0.5 points for when and why
  • 0.5 points for explanation

Scaling

Question 16 (1p)

Question

What is the main difference between vertical scaling and horizontal scaling?

Note: You don't need to explain each scaling approach in detail, only what the main difference between them is.

Sample answer

In vertical scaling, you simply replace the computer your application runs on with another one that is more powerful, i.e. a computer with a faster CPU, or more main memory, or more storage, etc.

In horizontal scaling, you instead run your application on multiple different computers at the same time, each of them doing a small part of the work that needs to be done in total.

Marking guidelines

  • 0.5 points for explaining that vertical scaling is using a more powerful computer
  • 0.5 points for explaining that horizontal scaling is using more computers

OR:

  • 0.25 points for correct explanations of both terms but having mixed them up

JavaScript

Question 17 (2p)

Question

The function getAccountById(id) returns a promise that resolves to a JS object with information about the account with the given id. If the account object can't be retrieved, the promise is rejected to a JS error object containing information about what went wrong.

The function getSentMessagesByAccountId(accountId) returns a promise that resolves to a JS array containing all messages an account with the given accountId has sent. If the array can't be retrieved, the promise is rejected to a JS error object containing information about what went wrong.

Implement the function getAccountAndSentMessagesByAccountId(accountId), that returns a promise that resolves to:

{
	account: THE_ACCOUNT_RETRIEVED_USING_getAccountById(),
	sentMessages: THE_MESSAGES_RETRIEVED_USING_getSentMessagesByAccountId()
}

If you get an error from getAccountById() or getSentMessagesByAccountId(), then your own promise should be rejected with the JS error object you get from the first one that was rejected.

It is OK to use async and await in your implementation.

Sample answer

async function getAccountAndSentMessagesByAccountId(accountId){
	
	const account = await getAccountById(accountId)
	const sentMessages = await getSentMessagesByAccountId(accountId)
	
	return {
		account,
		sentMessages,
	}
	
}

Marking guidelines

  • 2 points for a solution that is largely correct
  • Point reductions for errors:
    • -0.1 points for naming variables bad, such as ending with promise when it doesn't store a promise
    • -0.1 points for returning and throwing (both stops code execution in function, so no need to use return when you want to throw)
    • -0.25 points for creating local variables (e.g. in a try) and try to access them outside
    • -0.25 points for using try and catch
    • -0.25 points for returning error instead of throwing
    • -0.25 points for returning/throwing wrong error
    • -0.25 points for having unnecessary code
  • 0 points for a solution that:
    • Have a callback parameter/function, or
    • Try to read status codes or parse the response body (none of the given functions use HTTP)
    • Have SQL code (the data is not stored in a relational database)