Rfid scanner stops working after scanning the wrong card

It can scan the right card and it will display the working message but as soon as it scans the wrong card. It will stop working. I am sure that everything is properly connected. Here is my code:

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9
#define relay 2
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
int touchPin = 8;
unsigned long previousMillis = 0;        // will store last time LED was updated
unsigned long tacc = 5000UL;           // interval at which to blink (milliseconds)
boolean opened = false;
void setup()
{
  pinMode(touchPin, INPUT);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, HIGH);
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);
  Serial.println("Approximate your card to the reader...");
  Serial.println();
}
void loop()
{
  unsigned long currentMillis = millis();
  int touchValue = digitalRead(touchPin);
  if (touchValue == HIGH) {
    digitalWrite(relay, HIGH);
  }
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content = "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();
  if (content.substring(1) == "23 09 EF D3" ) {
  Serial.println("Authorized access");
    digitalWrite(relay, LOW);
    opened = true;
  }
  if (((unsigned long)(currentMillis - previousMillis) >= tacc) && (opened== true)) {
  digitalWrite(relay, HIGH);
    previousMillis = currentMillis;
    opened = false;
  }
}
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }

Does this bit of code work? Why don't you know?

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

What did, or didn't this do? Why don't you know?

It is completely unnecessary to convert the contents of a byte array to a String, so that you can compare it to another byte array converted to a String. Just compare the byte arrays.

  if (content.substring(1) == "23 09 EF D3" ) {

Why are you ignoring the first character?